使用场景
- 值接收者:适用于方法不改变接收者状态,并且接收者本身比较小(如基本类型、小型结构体)的场景。它是对接收者值的拷贝进行操作,原接收者不受影响。
- 指针接收者:适用于方法需要改变接收者状态,或者接收者是大型结构体,使用指针可以避免大量的数据拷贝,提高效率。
内存操作
- 值接收者:每次方法调用时会复制接收者的值,因此如果接收者是大型结构体,会占用较多内存,效率较低。
- 指针接收者:方法调用时传递的是指针,只需要复制指针大小的内存(通常是 4 字节或 8 字节),不会复制整个结构体,节省内存,适合大型结构体。
方法调用特性
- 值接收者:值类型变量既可以调用值接收者方法,也可以调用指针接收者方法(Go 语言会自动进行转换)。
- 指针接收者:指针类型变量既可以调用指针接收者方法,也可以调用值接收者方法(Go 语言会自动进行转换)。但是如果使用值类型调用指针接收者方法,Go 语言会自动取地址;如果使用指针类型调用值接收者方法,Go 语言会自动解引用。
示例
package main
import "fmt"
// 定义一个小型结构体
type SmallStruct struct {
Value int
}
// 值接收者方法
func (s SmallStruct) ValueMethod() {
s.Value++
fmt.Printf("值接收者方法中 s.Value: %d\n", s.Value)
}
// 指针接收者方法
func (s *SmallStruct) PointerMethod() {
s.Value++
fmt.Printf("指针接收者方法中 s.Value: %d\n", s.Value)
}
func main() {
small := SmallStruct{Value: 10}
// 值类型调用值接收者方法
small.ValueMethod()
fmt.Printf("调用值接收者方法后 small.Value: %d\n", small.Value)
// 值类型调用指针接收者方法,Go 语言自动取地址
small.PointerMethod()
fmt.Printf("调用指针接收者方法后 small.Value: %d\n", small.Value)
smallPtr := &SmallStruct{Value: 20}
// 指针类型调用值接收者方法,Go 语言自动解引用
smallPtr.ValueMethod()
fmt.Printf("调用值接收者方法后 smallPtr.Value: %d\n", smallPtr.Value)
// 指针类型调用指针接收者方法
smallPtr.PointerMethod()
fmt.Printf("调用指针接收者方法后 smallPtr.Value: %d\n", smallPtr.Value)
}
选择场景
- 选择值接收者:当方法不需要修改接收者状态,并且接收者本身是基本类型或者小型结构体时,选择值接收者。例如,计算一个整数的平方的方法,可以使用值接收者。
type Number int
func (n Number) Square() Number {
return n * n
}
- 选择指针接收者:当方法需要修改接收者状态,或者接收者是大型结构体时,选择指针接收者。例如,向一个大型用户信息结构体中添加新的联系方式的方法,应该使用指针接收者。
type User struct {
Name string
Age int
Contacts []string
}
func (u *User) AddContact(contact string) {
u.Contacts = append(u.Contacts, contact)
}