
在 Go 中,若为非结构体类型(如 type MyInt int)定义指针接收者方法,需通过解引用操作符 *i = newValue 修改原始值;直接赋值 i = &newValue 仅改变局部指针变量,不影响调用者持有的原始值。
在 go 中,若为非结构体类型(如 type myint int)定义指针接收者方法,需通过解引用操作符 `*i = newvalue` 修改原始值;直接赋值 `i = &newvalue` 仅改变局部指针变量,不影响调用者持有的原始值。
Go 允许为任意命名类型(包括基础类型的别名,如 type MyInt int)定义方法,但要修改调用者的原始值,必须确保修改的是指针所指向的内存位置,而非指针本身。
在原示例中:
func (i *MyInt) Change() {
newValue := MyInt(32)
i = &newValue // ❌ 错误:仅将局部指针 i 重新指向新变量,不改变原值
}
i 是一个形参,是调用时传入的指针副本。i = &newValue 只是让这个副本指向栈上新建的 newValue,而原始变量 myInt 的内存地址未被写入,因此 myInt 的值保持不变。
✅ 正确做法是使用解引用赋值,直接修改指针指向的内存内容:
func (i *MyInt) Change() {
*i = 32 // ✅ 正确:等价于 *i = MyInt(32),直接写入原内存位置
}
完整可运行示例:
package main
import "fmt"
type MyInt int
func (i *MyInt) Change() {
*i = 32 // 关键:解引用后赋值
}
func main() {
myInt := MyInt(64)
fmt.Println(myInt) // 输出:64
myInt.Change()
fmt.Println(myInt) // 输出:32
}
⚠️ 注意事项:
- 指针接收者方法必须由地址可取的值调用(如变量、字段、切片元素),不能用于字面量或不可寻址表达式(例如
MyInt(64).Change()会编译失败); - 若类型较大(如大数组或长字符串底层结构),即使不修改值,也建议用指针接收者以避免复制开销;
- 对于小类型(如
int、bool或小结构体),值接收者更清晰、更符合 Go 的惯用风格——除非明确需要修改状态。
总结:i = ... 改变的是指针变量本身;*i = ... 改变的是指针指向的值。这是理解 Go 指针语义的核心要点。










