*(指针符号)在以下Go方法中有什么不同?

时间:2015-01-14 09:11:07

标签: go

我遵循本教程:https://github.com/astaxie/build-web-application-with-golang/blob/master/en/02.5.md

我仍然不太了解指针,所以过去让我感到困惑:func (h *Human) SayHi()。我尝试删除*,输出结果完全相同。为什么*在这种情况下是必要的?有人可以用下面的代码给我一个不同输出的例子吗?

package main
import "fmt"

type Human struct {
    name string
    age int
    phone string
}

type Student struct {
    Human // anonymous field
    school string
}

type Employee struct {
    Human 
    company string
}

// define a method in Human
func (h *Human) SayHi() {
    fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}

func main() {
    mark := Student{Human{"Mark", 25, "222-222-YYYY"}, "MIT"}
    sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}

    mark.SayHi()
    sam.SayHi()
}

2 个答案:

答案 0 :(得分:3)

它的不同之处在于该方法将在指向Human结构的指针上定义,并且结构中的所有方法随后将对指向的值进行操作。

如果要松开*,该方法将对您调用方法的结构的副本进行操作,因此对方法中的结构执行的任何写操作都将对代码无效调用方法。

由于方法体仅执行fmt.Printf并打印一些值,因此如果在指针上定义了方法,它实际上并没有太大的区别。

在某些情况下,出于并发安全的考虑,最好不要在指针上定义方法,因为这可能导致同时访问和写入底层结构值。

答案 1 :(得分:1)

使用指针接收器有两个原因:

  1. 首先,为了避免在每个方法调用上复制值,如果值类型是一个大型结构,则效率更高。
  2. 其次,该方法可以修改其接收者指向的值。
  3. 因此,在您的示例中,如果您再添加一个转储方法来更改手机:

    func (h Human) ChangePhone() {
        h.phone = 'whatever'
    }
    

    拨打此方法后手机不会更改,这就是*点发挥作用的原因。