go中方法的接收者是值或者指针的区别

2017-06-20 17:33:10

type T struct {    Name string

}

func (t T) M1() {    t.Name = "name1"

}

func (t *T) M2() {    t.Name = "name2"

}

M1() 的接收者是值类型 T, M2() 的接收者是值类型 *T , 两个方法内都是改变Name值。

下面声明一个 T 类型的变量,并调用 M1() 和 M2() 。

t1 := T{"t1"}    fmt.Println("M1调用前:", t1.Name)    t1.M1()    fmt.Println("M1调用后:", t1.Name)    fmt.Println("M2调用前:", t1.Name)    t1.M2()    fmt.Println("M2调用后:", t1.Name)


输出结果为:

M1调用前: t1 M1调用后: t1 M2调用前: t1 M2调用后: name2

先来约定一下:接收者可以看作是函数的第一个参数,即这样的: func M1(t T)func M2(t *T)。 go不是面向对象的语言,所以用那种看起来像面向对象的语法来理解可能有偏差。

当调用 t1.M1() 时相当于 M1(t1) ,实参和行参都是类型 T,可以接受。此时在M1()中的t只是t1的值拷贝,所以M1()的修改影响不到t1。

当调用 t1.M2() => M2(t1),这是将 T 类型传给了 *T 类型,go可能会取 t1 的地址传进去: M2(&t1)。所以 M2() 的修改可以影响 t1 。

T 类型的变量这两个方法都是拥有的。

下面声明一个 *T 类型的变量,并调用 M1() 和 M2() 。

t2 := &T{"t2"}    fmt.Println("M1调用前:", t2.Name)    t2.M1()    fmt.Println("M1调用后:", t2.Name)    fmt.Println("M2调用前:", t2.Name)    t2.M2()    fmt.Println("M2调用后:", t2.Name)

输出结果为:

M1调用前: t2 M1调用后: t2 M2调用前: t2 M2调用后: name2

t2.M1() => M1(t2), t2 是指针类型, 取 t2 的值并拷贝一份传给 M1。

t2.M2() => M2(t2),都是指针类型,不需要转换。

*T 类型的变量也是拥有这两个方法的。