go中map等类型不可取地址,因其是值类型;修改需传指针或直接传值(如map、slice),append后须显式赋值;仅当需修改调用方变量内存时才必须用*t。

Go 里没有“引用”这个语言特性,只有指针;所谓“引用类型”是误称,本质是值类型,但内部含指针字段。
为什么 &map 会编译报错?
因为 map 是值类型,不是指针,不能对其取地址。它的零值是 nil,但你写 &m(m 是 map[string]int)时,Go 直接拒绝编译——cannot take the address of m。
-
map、slice、chan、func、interface{}都不允许用&取地址 - 它们的底层结构体里确实有指针(比如
map实际是*hmap包装),但对外不可见、不可操作 - 想让函数修改 map 的内容?直接传
m就够了;想让它指向新 map?必须传*map(极少见,且需显式解引用)
append 后原切片为啥没变?
因为 append 可能触发底层数组扩容,返回的是一个新 slice 结构体(含新指针、新 len/cap),而原变量仍持有旧结构体。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 没扩容时:
s2 := append(s1, x)→s2和s1共享底层数组,改s2[0]会影响s1[0] - 扩容后:
s2指向新数组,s1不受影响;此时s1和s2完全独立 - 别指望靠传参“自动更新”原 slice 变量——
append返回新值,必须显式赋值:s1 = append(s1, x)
什么时候非得用 *T 而不是 T?
只有一种情况:你要让函数内修改,**反映到调用方那个变量所指向的内存位置上**。
- 修改结构体字段(如
user.name = "x")→ 接收者用func (u *User) SetName(...) - 交换两个变量值 → 必须传
&a,&b,否则 swap 函数只改副本 - 避免大 struct 拷贝 →
type Big struct{ data [1,传 <code>*Big省空间 - 小 struct(如两个
int)传值反而更快,避免间接寻址开销
最容易被忽略的点:所有“引用类型”传参都是值传递,只是这个“值”里藏了指针;而真正的指针 *T 本身也是值——它被复制后,你只能改它指向的内容,不能让它在函数里改指向外部变量。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










