

新闻资讯
技术学院Go中值类型赋值是内存拷贝而非引用共享,包括基础类型、struct、array等;struct若含指针、slice、map等字段则仅拷贝头结构,底层数据仍共享,需手动深拷贝或显式传指针避免意外修改。
在 Go 中,值类型赋值本质是内存拷贝,不是引用共享。理解这一点,就能避开绝大多数“改了A,B也变了”或“改了A,B却没变”的困惑。
Go 的值类型包括:
关键判断标准:声明时不用 *,且变量直接持有数据本身 —— 赋值时就复制整块数据。
struct 是典型值类型。只要它的所有字段都是值类型,赋值就是完整拷贝:
示例:type User struct { Name string; Age int }
u1 := User{Name: "Alice", Age: 30}
u2 := u1 // ✅ 完全独立副本
u2.Name = "Bob"
fmt.Println(u1.Name, u2.Name) // Alice Bob
但如果 struct 含指针、slice、map、channel 或 func 字段,这些字段本身是引用类型 —— 它们存储的是地址,赋值时地址被复制,但指向的底层数据仍共享:
陷阱示例:type Config struct { Data map[string]int }
c1 := Config{Data: map[string]int{"x": 1}}
c2 := c1 // ❌ map header 被拷贝,但底层数组共用
c2.Data["x"] = 99
fmt.Println(c1.Data["x"]) // 输出 99 —— 意外修改!
这是
最容易混淆的点:slice/map/channel 变量本身是值类型(可赋值、传参不加 *),但它们内部包含指向底层数据的指针(如 slice 的 pointer/len/cap)。所以:
—— 对 slice 头修改(如重切片、追加扩容前)不影响原头;
—— 对底层元素修改(如 s[0] = x)会影响所有共享该数组的 slice。
明确意图,按需选择:
func update(u *User),并用 &u1 调用记住一句口诀:值类型赋值拷贝“自己”,不拷贝“自己指向的东西”。看清字段类型,就看清了共享边界。