Go语言-基于指针对象的方法(go语言指针和c指针区别)

在 Go 语言(Golang)中,方法可以绑定到结构体的 值类型指针类型。基于指针对象的方法有几个重要的特点和作用:

1.方法绑定到指针对象

当方法的接收者是指针类型时,它可以修改接收者的字段,并且能避免值拷贝,提高性能。

示例:使用指针对象的方法

package main

import (
 "fmt"
)

// 定义一个结构体
type Person struct {
 Name string
 Age  int
}

// 绑定到指针的修改方法
func (p *Person) GrowUp() {
 p.Age += 1
}

// 绑定到指针的修改方法
func (p *Person) ChangeName(newName string) {
 p.Name = newName
}

func main() {
 p1 := &Person{Name: "Alice", Age: 25}

 // 调用指针方法
 p1.GrowUp()
 p1.ChangeName("Bob")

 fmt.Println(*p1) // 输出:{Bob 26}
}

解析

  • func (p *Person) GrowUp() 绑定到 *Person,它能修改 Age。
  • func (p *Person) ChangeName(newName string) 绑定到 *Person,可以修改 Name。
  • 在 main() 中,使用 p1.GrowUp() 和 p1.ChangeName(),成功修改了结构体的字段。

2.指针方法的必要性

(1)修改结构体字段

如果方法的接收者是值类型(Person),那么方法内部对 p.Age 和 p.Name 的修改只会影响副本,而不会影响原始对象。因此,如果方法需要修改对象本身,必须使用指针接收者。

func (p Person) GrowUpWrong() {
 p.Age += 1
}

上面的 GrowUpWrong() 不能真正修改 p.Age,因为 p 是一个副本。

(2)避免值拷贝,提高性能

如果结构体比较大(例如包含多个字段或切片),使用值传递会导致拷贝成本增加。而指针接收者只传递一个指针,避免了不必要的拷贝。

type LargeStruct struct {
 Data [1000]int
}

// 使用指针方法避免拷贝
func (ls *LargeStruct) Modify() {
 ls.Data[0] = 999
}

3.值方法 vs. 指针方法

值方法(Value Receiver)

  • 方法接收者是一个值副本,不影响原结构体。
  • 适用于不修改字段的场景,如 Print(), GetName() 之类的操作。

指针方法(Pointer Receiver)

  • 方法接收者是指针,能修改原对象的字段。
  • 适用于需要修改结构体的场景,如 ChangeName(), GrowUp()。

示例:值方法 vs. 指针方法

package main

import "fmt"

type Animal struct {
 Name string
}

// 值方法:不会修改原结构体
func (a Animal) SetNameWrong(newName string) {
 a.Name = newName
}

// 指针方法:可以修改原结构体
func (a *Animal) SetName(newName string) {
 a.Name = newName
}

func main() {
 a1 := Animal{Name: "Cat"}

 a1.SetNameWrong("Dog")
 fmt.Println(a1.Name) // 仍然是 "Cat"

 a1.SetName("Dog")
 fmt.Println(a1.Name) // 修改成功,输出 "Dog"
}

4.指针方法的自动调用

Go 语言允许在 值对象 上调用 指针方法,Go 编译器会自动转换:

type Counter struct {
 Count int
}

func (c *Counter) Increase() {
 c.Count++
}

func main() {
 c1 := Counter{Count: 10}

 // 即使是值对象,也可以调用指针方法,Go 会自动取地址
 c1.Increase()
 fmt.Println(c1.Count) // 输出 11
}

指针对象也可以调用值方法(Go 自动解引用):

func (c Counter) Show() {
 fmt.Println(c.Count)
}

func main() {
 c2 := &Counter{Count: 20}

 // 不能自动转换为值方法,必须手动解引用
 c2.Show() // Go 编译器允许 实际等价于 (*c2).Show()
 (*c2).Show() // 手动解引用
}

Go 编译器允许 c2.Show(),因为它会自动解引用 c2 变成 (*c2).Show()。


5.总结

方法接收者

能修改字段

是否拷贝结构体

适用场景

值方法(T)

(会拷贝)

适用于只读方法

指针方法(*T)

(无拷贝)

需要修改结构体字段或避免大结构体拷贝

最佳实践

  • 修改结构体字段 → 使用指针方法。
  • 结构体较大 → 使用指针方法,避免拷贝。
  • 简单只读操作 → 使用值方法,提高可读性。

如果不确定用哪种方式,优先使用指针方法 func (p *T) MethodName(),因为它适用范围更广。

原文链接:,转发请注明来源!