Golang中结构体变量未按预期递增的问题
Golang中结构体变量未按预期递增的问题 大家好, 我有以下Go代码:
package a
type A struct {
...
x int
...
}
////
package B
...
x map[string]a.A
...
func GetValByKey(key string) (a.A, bool) {
val, exist := x[key]
return val, exist
}
////
package C
func abc(c *gin.Context) {
ws, err := WsUpgrader.Upgrade(c.Writer, c.Request, nil)
defer ws.Close()
...
val, ok := GetValByKey(key)
val.x++
...
go handleEvents()
for {
...
}
}
现在,当我使用相同的键调用端点时,x的值在两种情况下都是从0开始增加的。即: 第一次调用, x的值(++之前):= 0 x的值(++之后):= 1 第二次调用, x的值(++之前):= 0 x的值(++之后):= 1 但对于第二次调用,我希望它是: x的值(++之前):= 1 x的值(++之后):= 2 我无法弄清楚问题可能出在哪里。你能帮忙吗?
更多关于Golang中结构体变量未按预期递增的问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
结构体不是按值拷贝的吗?所以每次你调用 GetValByKey(key) 时,它返回的都是该结构体的一个副本。
更多关于Golang中结构体变量未按预期递增的问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你是否需要将映射的值改为指向值的指针?类似下面这样:
package main
import (
"fmt"
"os"
)
type a struct {
x int
}
type mapStrToAPtr map[string]*a
func getPtrValByKey(key string, m mapStrToAPtr) (*a, bool) {
val, exist := m[key]
return val, exist
}
func main() {
m := map[string]*a{
"G4143": {4143},
"Emily": {1234},
"Angela": {4321},
}
for key, value := range m {
fmt.Fprintf(os.Stdout, "%s -> %d\n", key, *value)
}
if p, ok := getPtrValByKey("G4143", m); ok {
p.x++
}
for key, value := range m {
fmt.Fprintf(os.Stdout, "%s -> %d\n", key, *value)
}
}
问题在于你的代码中每次调用GetValByKey返回的是结构体的副本,而不是原始值。在Go中,map返回的是值的副本,对副本的修改不会影响map中存储的原始值。
以下是修复后的代码示例:
package a
type A struct {
X int
}
package b
import "a"
var data = make(map[string]a.A)
func GetValByKey(key string) (a.A, bool) {
val, exist := data[key]
return val, exist
}
func UpdateValByKey(key string, val a.A) {
data[key] = val
}
package c
import (
"a"
"b"
"github.com/gin-gonic/gin"
)
func abc(c *gin.Context) {
ws, err := WsUpgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close()
key := "some_key"
val, ok := b.GetValByKey(key)
if !ok {
val = a.A{X: 0}
}
val.X++
b.UpdateValByKey(key, val)
go handleEvents()
for {
// 处理逻辑
}
}
或者,你可以使用指针来存储结构体,这样可以直接修改原始值:
package a
type A struct {
X int
}
package b
import "a"
var data = make(map[string]*a.A)
func GetValByKey(key string) (*a.A, bool) {
val, exist := data[key]
return val, exist
}
package c
import (
"a"
"b"
"github.com/gin-gonic/gin"
)
func abc(c *gin.Context) {
ws, err := WsUpgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
return
}
defer ws.Close()
key := "some_key"
val, ok := b.GetValByKey(key)
if !ok {
val = &a.A{X: 0}
b.data[key] = val
}
val.X++
go handleEvents()
for {
// 处理逻辑
}
}
在第二个方案中,由于map存储的是指针,对val.X的修改会直接反映到map中的原始值上。注意,使用指针时需要确保并发安全,可以考虑使用sync.RWMutex来保护map的访问。

