Go中值类型传参不改变原变量,指针传地址可修改;string是带指针字段的值类型,非引用类型;指针比较默认比地址;接口实现时 T方法集包含T和 T方法,T方法集仅含T接收者方法。

基础类型传值 vs 指针传地址:改不改得到原变量?
Go 中 int、string、bool、小 struct 这些都是值类型,函数传参时复制整个值——你在函数里改它,外面完全没反应。*int、*string 这类指针则只传一个地址(8 字节),函数内通过 *p 解引用就能直接读写原始内存。
- 想修改调用方的变量?必须传
*T,比如func increment(n *int) { *n++ } - 只读取、不修改,且类型小(如
Point {x, y int})?传值更安全、语义更清晰 - 常见错误:
func setName(p Person) { p.Name = "X" }—— 外部Person实例的Name不会变
为什么 string 是值类型,却“看起来像引用”?
string 本身是值类型(底层是 struct{data *byte, len int}),赋值时复制的是这个结构体,不是底层数组。所以两个 string 变量可以共享同一片底层字节,但它们的头信息(地址+长度)是独立的。
- 你不能通过一个
string变量去修改另一个的底层内容(因为不可变) - 但
s1 == s2比较的是内容,不是地址——这是string的特殊约定,和指针行为无关 - 别误以为
string是引用类型;它既不是slice也不是指针,只是“带指针字段的值类型”
指针比较默认比地址,不是比内容
两个 *int 用 == 判断,结果只取决于它们是否指向同一个变量,跟值一不一样完全无关。
-
a, b := 42, 42; p1, p2 := &a, &b; p1 == p2→false(不同变量,哪怕值相同) -
p1 == nil安全,但*p1 == *p2前必须确保两者都不为nil,否则 panic - 想比内容?先判空再解引用:
p1 != nil && p2 != nil && *p1 == *p2;复杂结构用reflect.DeepEqual - 跨类型指针(如
*int和*float64)不能直接==,编译报错;非必要别碰unsafe.Pointer
接口实现时,值类型和指针类型的方法集完全不同
一个类型 T 的方法集,只包含接收者为 func (t T) M() 的方法;而 *T 的方法集包含 func (t T) M() 和 func (t *T) M() 全部方法。
立即学习“go语言免费学习笔记(深入)”;
- 如果你只写了
func (u *User) Save() error,那么User{}实例无法赋给Saver接口变量 - 常见报错:
cannot use u (type User) as type Saver in argument to doSave: User does not implement Saver - 修复方式:要么把参数改成
*User,要么补一个值接收者方法(但通常没必要) - 结构体字段含指针(如
Age *int)不影响接口实现,只影响该字段能否为nil或区分“未设置”与“零值”










