法總是綁定對象實例,並隱式將實例作爲第⼀實參 (receiver)。
• 只能爲當前包內命名類型定義⽅法。
• 參數 receiver 可任意命名。如⽅法中未曾使⽤,可省略參數名。
• 參數 receiver 類型可以是 T 或 *T。基類型 T 不能是接⼝或指針。
• 不⽀持⽅法重載, receiver 只是參數簽名的組成部分。
• 可⽤實例 value 或 pointer 調⽤全部⽅法,編譯器⾃動轉換。
• Go 不允許同名函數,但是同名方法可以定義在不同的類型上
• method和receiver必須在同一個包裏定義
• 作爲函數參數,值類型就是值類型,指針類型就是指針類型
• 方法有一個值類型和指針類型的接受者時,都可以直接調用,內部會
自動進行語法的轉換。
一個方法只是一個函數,它有一個特殊的接收者(receiver)類型,該接收者放在 func 關鍵字和函數名之間。接收者可以是結構體類型或非結構體類型。可以在方法內部訪問接收者。
一般語法爲:
func (t receiver_type) methodName(parameter list) {}
一、參數 receiver 類型可以是 T 或 *T。以指針爲接收者也是可以的。
兩者的區別在於, 以*T爲接收者時,方法內部對其的修改對於外部有效,而以 T作爲接受者時,對於外部無效。
1func (e Employee) changeName(newName string) {
2 e.name = newName
3}
4func (e *Employee) changeAge(newAge int) {
5 e.age = newAge
6}
7 emp1 := Employee{
8 name: "張三",
9 salary: 6000,
10 currency: "$",
11 age: 18,
12 Address: Address{"山東", "濟南"},
13 }
14 emp1.displaySalary()
15
16 fmt.Println("Before call changeName ", emp1.name)
17 //修改名字,未發生變化因爲是值傳遞
18 emp1.changeName("zhangsan")
19 fmt.Println("After call changeName ", emp1.name) //After call changeName 張三
20
21 fmt.Println("Before change age", emp1.age)
22 //利用指針來修改年齡
23 emp1.changeAge(50)
24 fmt.Println("After change age", emp1.age) //After change age 50
二、Go 不允許同名函數,但是同名方法可以定義在不同的類型上
1//Rectangle 代碼規範
2type Rectangle struct {
3 width float32
4 height float32
5}
6//Circle 代碼規範
7type Circle struct {
8 radius float32
9}
10func (e Employee) changeName(newName string) {
11 e.name = newName
12}
13func (e *Employee) changeAge(newAge int) {
14 e.age = newAge
15}
16func main() {
17 //計算面積
18 re := Rectangle{20, 30}
19 c := Circle{40}
20 //兩個類型調用同名方法
21 fmt.Println(re.getArea())
22 fmt.Println(c.getArea())
23}
1emp1 := Employee{
2 name: "張三",
3 salary: 6000,
4 currency: "$",
5 age: 18,
6 Address: Address{"山東", "濟南"},
7 }
8 //提階
9 emp1.fullAddress() //山東 濟南,提階相當於直接訪問Address裏的
10 emp1.Address.fullAddress() //山東 濟南
四、非結構類型的方法
非結構體類型也可以定義方法,不過這裏需要注意一點。爲了定義某個類型的方法,接收者類型的定義與方法的定義必須在同一個包中。
因爲必須在一個包中而int則在main包中我們沒法去定義這個裏爲了簡單直觀,給int聲明瞭別名
1//非結構體方法擴展
2type myInt int
3
4func (a myInt) add(b myInt) myInt {
5 return a + b
6}
7func main() {
8 //調用擴展的方法
9 num1 := myInt(5)
10 num2 := myInt(10)
11 sum := num1.add(num2)
12 fmt.Println("Sum is", sum)
13
14}
下面附上完整實例程序
1package main
2
3import (
4 "fmt"
5 "math"
6)
7
8//Employee 需要添加註釋或者改成非導出變量(首字母小寫)
9type Employee struct {
10 name string
11 currency string
12 salary int
13 age int
14 Address
15}
16
17//Address 代碼規範
18type Address struct {
19 city string
20 state string
21}
22
23//Rectangle 代碼規範
24type Rectangle struct {
25 width float32
26 height float32
27}
28
29//Circle 代碼規範
30type Circle struct {
31 radius float32
32}
33
34//Employee 的方法
35func (e Employee) displaySalary() {
36 fmt.Println(e)
37}
38func (e Employee) changeName(newName string) {
39 e.name = newName
40}
41func (e *Employee) changeAge(newAge int) {
42 e.age = newAge
43}
44
45//Address 的方法
46func (add Address) fullAddress() {
47 fmt.Println(add.city, add.state)
48}
49
50//Rectangle 的方法計算面積
51func (r Rectangle) getArea() float32 {
52 return r.width * r.height
53}
54
55//Circle 的方法
56func (c Circle) getArea() float32 {
57 return math.Pi * c.radius * c.radius
58}
59
60//非結構體方法擴展
61type myInt int
62
63func (a myInt) add(b myInt) myInt {
64 return a + b
65}
66func main() {
67 //調用方法
68 emp1 := Employee{
69 name: "張三",
70 salary: 6000,
71 currency: "$",
72 age: 18,
73 Address: Address{"山東", "濟南"},
74 }
75 emp1.displaySalary()
76
77 fmt.Println("Before call changeName ", emp1.name)
78 //修改名字,未發生變化因爲是值傳遞
79 emp1.changeName("zhangsan")
80 fmt.Println("After call changeName ", emp1.name) //After call changeName 張三
81
82 fmt.Println("Before change age", emp1.age)
83 //利用指針來修改年齡
84 emp1.changeAge(50)
85 fmt.Println("After change age", emp1.age) //After change age 50
86
87 //提階
88 emp1.fullAddress() //山東 濟南,提階相當於直接訪問Address裏的
89 emp1.Address.fullAddress() //山東 濟南
90
91 //計算面積
92 re := Rectangle{20, 30}
93 c := Circle{40}
94 //兩個類型調用同名方法
95 fmt.Println(re.getArea())
96 fmt.Println(c.getArea())
97
98 //調用擴展的方法
99 num1 := myInt(5)
100 num2 := myInt(10)
101 sum := num1.add(num2)
102 fmt.Println("Sum is", sum)
103
104}
原文發佈時間爲:2018-12-12
本文作者:Golang語言社區
本文來自雲棲社區合作伙伴“ Golang語言社區”,瞭解相關信息可以關注“Golangweb”微信公衆號