指针接收者方法

* 本页面主要介绍Go语言指针接收者方法的相关内容。

方法基础 一节中,我们已经学习了Go方法的基础知识,今天这节我们主要围绕基于指针对象的方法来深入讨论总结一下。

基于指针对象的方法

我们知道,Go语言中参数传递都是值传递。当我们需要更新一个变量,或者参数较大时,我们希望能够避免这样的拷贝,这个时候我们就需要用到指针了。所以,对应的 我们用指针来作为接收器,就达到了同样的目的。

  //方法名字是(*Point).ScaleBy,注意这里的括号是必须的
  func (p *Point) ScaleBy(factor float64) {
      p.X *= factor
      p.Y *= factor
  }

  //常规调用
  r := &Point{1, 2}
  r.ScaleBy(2)
  fmt.Println(*r) // "{2, 4}"

  //简短调用
  //编译器会隐式地帮我们用&p去调用ScaleBy这个方法
  p := Point{1, 2}
  p.ScaleBy(2)

值接收者声明的方法,调用时会使用这个值的一个副本去执行,而指针接收者在调用者会共享调用方法时接收者所指向的值,即可以修改指向的值。

一般来讲,如果某一个类(比如上面示例程序中的Point)中有一个指针作为接收器的方法,那么所有Point的方法都必须有一个指针接收器,即使是那些并不需要这个指针接收器的函数。 另外,如果一个类型名本身是一个指针的话,是不允许其出现在接收器中的

  type P *int
  func (P) f() { /* ... */ } // compile error: invalid receiver type

关于拷贝相关的,有一个特别需要注意的地方:

  • 如果命名类型T的所有方法都是用T类型自己来做接收器(而不是*T),那么拷贝这种类型的实例就是安全的;调用他的任何一个方法也就会产生一个值的拷贝。
  • 如果命名类型T的一个方法使用指针作为接收器,那么拷贝这种类型的实例就是不安全的;你需要避免对其进行拷贝,因为这样可能会破坏掉该类型内部的不变性。对拷贝后的变量进行修改可能会有让你有意外的结果。
Nil是一个合法的接收器类型

方法理论上可以用nil指针作为其接收器,尤其当nil对于对象来说是合法的零值时,比如map或者slice。在下面的简单int链表的例子里,nil代表的是空链表(注意这个时候对于nil代表的含义有一个明确的注释变得非常重要):

  // An IntList is a linked list of integers.
  // A nil *IntList represents the empty list.
  type IntList struct {
      Value int
      Tail  *IntList
  }
  // Sum returns the sum of the list elements.
  func (list *IntList) Sum() int {
      if list == nil {
          return 0
      }
      return list.Value + list.Tail.Sum()
  }

指针类型接收者方法就总结到这里,你Get了吗?


* 本页内容参考以下数据源:

  • 《Go程序设计语言》
  • https://www.jianshu.com/p/7811d96c7eeb

凯冰科技 · 代码改变世界,技术改变生活
Next Page→