go學習(十七)go可以為任意類型定義方法!!


可以先看:go的數據類型
下面是針對不同類型,方法如何定義和使用。

1、方法定義

go可以為任意類型定義方法!!【指針類型除外】

方法比函數的好處:方法名可以簡短。當我們在包外調用的時候這種好處就會被放大,因為我們可以使用這個短名字,而可以省略掉包的名字。

在函數聲明時,在其名字之前放上一個變量,即是一個方法。這個附加的參數會將該函數附加到這種類型上,即相當於為這種類型定義了一個獨占的方法。

(1)兩種接收器聲明方式:

接收器是類型對象

func (p Point) ScaleBy(factor float64) {xx}

接收器是類型指針對象
一般會約定如果Point這個類有一個指針作為接收器的方法,那么所有Point的方法都必須有一個指針接收器,即使是那些並不需要這個指針接收器的函數。

func (p *Point) ScaleBy(factor float64) {xx}

(2)指針類型的方法

go不能直接定義指針類型的方法!!!說的是下面這種情況,因為接收器放類型和指針都不對:

type intPoint *int
//func (?) addThree() int{
//  return 
//}
func main(){
  tmp := 10
  var b intPoint = &tmp
  // fmt.Print(b.addThree()) //指針類型的方法addThree沒法定義,當然也就沒法調用
}

但是,我們可以換個方式,用指針變量調用指針對應原類型的方法。調用方式有2種:

type myInt int
func (i myInt) addOne() myInt {
  return i + 1
}
func (i *myInt) addTwo() myInt {
  return *i + 2
}
func main(){
  //方式1
  var a myInt = 2 // a是myInt類型
  a.addOne() // a不變
  fmt.Println(a) // 2
  (&a).addTwo() //取地址即指針。傳指針,a變
  fmt.Println(a) // 4

  //方式2
  b := new(myInt) // b是*myInt類型,指針
  *b = 10
  // 傳值,b不變
  (*b).addOne() // 正常訪問,傳入myInt類型
  fmt.Println(*b)
  b.addOne() // go自己處理,傳入*myInt自動轉為myInt類型
  fmt.Println("b:", *b)
  //下面傳入指針,b會變
  b.addTwo() // 正常訪問,傳入*myInt類型。
  fmt.Println(*b)
  (*b).addTwo() // go自己處理,傳入myInt自動轉為*myInt類型
  fmt.Println(*b)
}

(3)

如果命名類型T(譯注:用type xxx定義的類型)的所有方法都是用T類型自己來做接收器(而不是*T),那么拷貝這種類型的實例就是安全的;調用他的任何一個方法也就會產生一個值的拷貝。比如time.Duration的這個類型,在調用其方法時就會被全部拷貝一份,包括在作為參數傳入函數的時候。

但是如果一個方法使用指針作為接收器,你需要避免對其進行拷貝,因為這樣可能會破壞掉該類型內部的不變性。比如你對bytes.Buffer對象進行了拷貝,那么可能會引起原始對象和拷貝對象只是別名而已,實際上它們指向的對象是一樣的。緊接着對拷貝后的變量進行修改可能會有讓你有意外的結果。

譯注: 作者這里說的比較繞,其實有兩點:

1 不管你的method的receiver是指針類型還是非指針類型,都是可以通過指針/非指針類型進行調用的,編譯器會幫你做類型轉換。
2 在聲明一個method的receiver該是指針還是非指針類型時,你需要考慮兩方面的因素,第一方面是這個對象本身是不是特別大,如果聲明為非指針變量時,調用會產生一次拷貝;第二方面是如果你用指針類型作為receiver,那么你一定要注意,這種指針類型指向的始終是一塊內存地址,就算你對其進行了拷貝。熟悉C或者C++的人這里應該很快能明白。//沒懂

參考:
https://blog.csdn.net/u013862108/article/details/105028124
https://docs.hacknode.org/gopl-zh/ch6/ch6-02.html

2、實現接口的表示:接收器不能是指針!!

接收參數person不可以是指針類型,否則不認為是實現了接口

參考:
https://www.cnblogs.com/craneboos/p/8615476.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM