天天看點

清華尹成帶你實戰GO案例(28)Go 方法

Go 方法

一般的函數定義叫做函數,定義在結構體上面的函數叫做該結構體的方法。

示例1:

package main
import "fmt"
type rect struct {
width, height int
}
// 這個area方法有一個限定類型*rect,
// 表示這個函數是定義在rect結構體上的方法
func (r *rect) area() int {
return r.width * r.height
}
// 方法的定義限定類型可以為結構體類型
// 也可以是結構體指針類型
// 差別在于如果限定類型是結構體指針類型
// 那麼在該方法内部可以修改結構體成員資訊
func (r rect) perim() int {
return 2*r.width + 2*r.height
}
func main() {
r := rect{width: 10, height: 5}
// 調用方法
fmt.Println("area: ", r.area())
fmt.Println("perim:", r.perim())
// Go語言會自動識别方法調用的參數是結構體變量還是
// 結構體指針,如果你要修改結構體内部成員值,那麼使用
// 結構體指針作為函數限定類型,也就是說參數若是結構體
//變量,僅僅會發生值拷貝。
rp := &r
fmt.Println("area: ", rp.area())
fmt.Println("perim:", rp.perim())
}           

輸出結果為

area: 50

perim: 30

示例2:

從某種意義上說,方法是函數的“文法糖”。當函數與某個特定的類型綁定,那麼它就是一個方法。也證

因為如此,我們可以将方法“還原”成函數。

instance.method(args)->(type).func(instance,args)

為了差別這兩種方式,官方文檔中将左邊的稱為 Method Value ,右邊則是 Method Expression 。

Method Value是包裝後的狀态對象,總是與特定的對象執行個體關聯在一起(類似閉包,拐帶私奔),而

Method Expression函數将Receiver作為第一個顯式參數,調用時需額外傳遞。

注意:對于Method Expression,T僅擁有T Receiver方法, T擁有(T+ T)所有方法。

package main
import (
"fmt"
)
func main() {
p := Person{2, "張三"}
p.test(1)
var f1 func(int) = p.test
f1(2)
Person.test(p, 3)
var f2 func(Person, int) = Person.test
f2(p, 4)
}
type Person struct {
Id int
Name string
}
func (this Person) test(x int) {
fmt.Println("Id:", this.Id, "Name", this.Name)
fmt.Println("x=", x)
}           

輸出結果:

Id: 2 Name 張三

x= 1

x= 2

x= 3

x= 4

示例3:

使用匿名字段,實作模拟繼承。即可直接通路匿名字段(匿名類型或匿名指針類型)的方法這種行為類

似“繼承”。通路匿名字段方法時,有隐藏規則,這樣我們可以實作override效果。

package main
import (
"fmt"
)
func main() {
p := Student{Person{2, "張三"}, 25}
p.test()
}
type Person struct {
Id int
Name string
}
type Student struct {
Person
Score int
}
func (this Person) test() {
fmt.Println("person test")
}
func (this Student) test() {
fmt.Println("student test")
}           

輸出結果為:

student test

清華尹成帶你實戰GO案例(28)Go 方法
清華尹成帶你實戰GO案例(28)Go 方法

網址:http://www.qukuailianxueyuan.io/

清華尹成帶你實戰GO案例(28)Go 方法
清華尹成帶你實戰GO案例(28)Go 方法
清華尹成帶你實戰GO案例(28)Go 方法
清華尹成帶你實戰GO案例(28)Go 方法