package main import "fmt" // 定义一个 Person 结构体 type Person struct { Name string Age int } // ========== 值接收者方法 ========== func (p Person) SayHello() { fmt.Printf("Hello, I'm %s (值接收者)\n", p.Name) } // 值接收者无法修改原始结构体字段 func (p Person) SetName(name string) { p.Name = name // 修改的是副本! fmt.Printf("在值接收者中设置 Name = %s\n", p.Name) } // ========== 指针接收者方法 ========== func (p *Person) SayHelloPtr() { fmt.Printf("Hello, I'm %s (指针接收者)\n", p.Name) } // 指针接收者可以真正修改原始结构体 func (p *Person) SetNamePtr(name string) { p.Name = name // 修改的是原始对象! fmt.Printf("在指针接收者中设置 Name = %s\n", p.Name) } // ========== 对比调用行为 ========== func main() { fmt.Println("=== 1. 使用值类型变量调用方法 ===") p1 := Person{Name: "Alice", Age: 30} p1.SayHello() // OK p1.SetName("Alicia") // ❌ 不会改变 p1.Name fmt.Printf("调用值接收者 SetName 后,p1.Name = %s\n", p1.Name) p1.SayHelloPtr() // ✅ Go 自动取地址 (&p1) p1.SetNamePtr("Anna") // ✅ 真正修改了 p1 fmt.Printf("调用指针接收者 SetNamePtr 后,p1.Name = %s\n", p1.Name) fmt.Println("\n=== 2. 使用指针类型变量调用方法 ===") p2 := &Person{Name: "Bob", Age: 25} p2.SayHello() // ✅ Go 自动解引用 (*p2) p2.SayHelloPtr() // ✅ 直接调用 p2.SetName("Bobby") // ❌ 副本修改,无效 fmt.Printf("调用值接收者 SetName 后,p2.Name = %s\n", p2.Name) p2.SetNamePtr("Robert") // ✅ 真正修改 fmt.Printf("调用指针接收者 SetNamePtr 后,p2.Name = %s\n", p2.Name) fmt.Println("\n=== 3. 关键规则总结 ===") fmt.Println("- 值接收者:操作副本,不能修改原结构体") fmt.Println("- 指针接收者:操作原始数据,可修改") fmt.Println("- Go 会自动处理 & 和 * 转换(只要变量可寻址)") fmt.Println("- 如果方法需要修改字段,请使用指针接收者!") }