方法的调用者既可以是值也可以是指针,Go语言会帮我们自动转义

28 min read

为了理解这个问题,首先需要理解函数参数的传递方式。

在 Go 语言中,参数传递有两种方式:

  1. 值传递(pass by value):函数参数是原始值的副本,对参数的修改不会影响原始值。

  2. 引用传递(pass by reference):函数参数是原始值的指针,对参数的修改会影响原始值。

当我们调用一个函数时,编译器会根据参数类型和函数签名来决定参数传递方式。如果参数是原始值类型,那么就会使用值传递;如果参数是指针类型,那么就会使用引用传递。

但是,在 Go 语言中,函数的参数类型可以是指针类型或者值类型。因此,方法的调用者既可以是值也可以是指针类型。

例如:

type Person struct {
    Name string
    Age  int
}

// 值类型方法
func (p Person) SayHello() {
    fmt.Println("Hello, my name is", p.Name)
}

// 指针类型方法
func (p *Person) ChangeAge(newAge int) {
    p.Age = newAge
}

func main() {
    p := Person{"Alice", 20}

    // 值类型调用方法
    p.SayHello() // 输出:Hello, my name is Alice

    // 指针类型调用方法
    p.ChangeAge(30)
    fmt.Println(p.Age) // 输出:30

    // 值类型变量调用指针类型方法
    (&p).ChangeAge(40)
    fmt.Println(p.Age) // 输出:40

    // 指针类型变量调用值类型方法
    (*&p).SayHello() // 输出:Hello, my name is Alice
}

在上面的例子中,我们定义了一个 Person 结构体,并为其定义了一个值类型方法 SayHello() 和一个指针类型方法 ChangeAge()

我们可以使用值类型变量 p 来调用值类型方法 SayHello(),也可以使用指针类型变量 &p 来调用指针类型方法 ChangeAge()。这一点,编译器会根据方法的参数类型来决定参数传递方式。

另外,我们也可以使用值类型变量来调用指针类型方法 ChangeAge(),或者使用指针类型变量来调用值类型方法 SayHello()。这时,编译器会自动转义变量类型,使其符合方法的参数类型。