Golang學習筆記之方法(method)

法總是綁定對象實例,並隱式將實例作爲第⼀實參 (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”微信公衆號

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章