接口是方法签名集合,任何类型实现其方法即满足;指针控制内存地址访问权限,仅指针能调用指针接收者方法并修改原值。

理解指针与接口在 Go 中的本质区别
Go 里没有传统面向对象的“继承”或“虚函数表”,但通过接口和指针配合,能自然实现多态和引用语义。接口是**一组方法签名的集合**,任何类型只要实现了这些方法,就自动满足该接口;而指针则控制着值的**内存地址访问权限**——只有指针才能调用接收者为指针的方法,也才能修改原值。
用指针接收者实现可变行为(引用传递效果)
当方法需要修改结构体字段时,必须使用指针接收者。这不仅让调用方看到变化,还影响接口实现关系:
- 如果接口方法签名要求指针接收者,那么只有 *T 类型能实现它,T 值类型不行
- 传参时若用 &v,函数内对结构体字段的修改会反映到原变量上
- 直接传 v(值拷贝)时,即使方法是值接收者,也无法改变调用方的原始数据
通过接口变量实现运行时多态
接口变量本身存储的是动态类型(具体类型)和动态值(或其指针)。只要多个类型实现了同一接口,就能统一处理:
- 定义 type Shape interface { Area() float64 }
- 让 Circle 和 Rectangle 分别实现 Area() 方法(可都用值接收者,也可都用指针接收者)
- 把 &Circle{} 或 Rectangle{} 赋给 Shape 变量,调用 s.Area() 会自动分发到对应类型的具体实现
小心空指针与 nil 接口的组合陷阱
接口变量为 nil,并不意味着底层值一定为 nil;反过来,*T 类型变量为 nil 时,若方法是指针接收者且被接口调用,会 panic:
立即学习“go语言免费学习笔记(深入)”;
- var s Shape = (*Circle)(nil) 是合法的,s != nil(因为接口包含类型信息)
- 但此时调用 s.Area() 会 panic:runtime error: invalid memory address
- 安全做法是在指针接收者方法开头加 if r == nil { return 0 } 防御性检查










