Golang教程:方法


什么是方法

一個方法只是一個函數,它有一個特殊的接收者(receiver)類型,該接收者放在 func 關鍵字和函數名之間。接收者可以是結構體類型或非結構體類型。可以在方法內部訪問接收者。

通過下面的語法創建一個方法:

func (t Type) methodName(parameter list) {  
}

上面的代碼片段創建了一個名為 methodName 的方法,該方法有一個類型為 Type 的接收者。

例子

讓我們編寫一個簡單的程序,它創建一個結構體類型的方法並調用它。

package main

import (  
    "fmt"
)

type Employee struct {  
    name     string
    salary   int
    currency string
}

/*
 displaySalary() method has Employee as the receiver type
*/
func (e Employee) displaySalary() {  
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {  
    emp1 := Employee {
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    emp1.displaySalary() //Calling displaySalary() method of Employee type
}

上面程序的第 6 行,我們創建了 Employee 的一個名為 displaySalary 的方法。在 displaySalary() 方法內部可以訪問它的接收者 e (類型為 Employee)。在第 17 行,我們使用接收者 e,並打印它的 namecurrency 以及 salary

在第26行,我們使用 emp1.displaySalary() 這樣的語法來調用方法。

程序的輸出為:Salary of Sam Adolf is $5000

為什么使用方法而不是函數?

上面的程序可以使用函數而不是方法重寫如下

package main

import (  
    "fmt"
)

type Employee struct {  
    name     string
    salary   int
    currency string
}

/*
 displaySalary() method converted to function with Employee as parameter
*/
func displaySalary(e Employee) {  
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {  
    emp1 := Employee{
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    displaySalary(emp1)
}

在上面的程序中,我們使用 displaySalary 函數替換了方法,並將 Employee 結構體作為參數傳給它。該程序的輸出與上面的程序輸出一樣:Salary of Sam Adolf is $5000

為什么使用方法而不是函數?

上面的程序可以使用函數而不是方法重寫如下:

package main

import (  
    "fmt"
)

type Employee struct {  
    name     string
    salary   int
    currency string
}

/*
 displaySalary() method converted to function with Employee as parameter
*/
func displaySalary(e Employee) {  
    fmt.Printf("Salary of %s is %s%d", e.name, e.currency, e.salary)
}

func main() {  
    emp1 := Employee{
        name:     "Sam Adolf",
        salary:   5000,
        currency: "$",
    }
    displaySalary(emp1)
}

在上面的程序中,我們使用 displaySalary 函數替換了方法,並將 Employee 結構體作為參數傳給它。該程序的輸出與上面的程序輸出一樣:Salary of Sam Adolf is $5000

那么為什么我們可以用函數完成同樣的工作,卻還要使用方法呢?這里有幾個原因,我們一個一個地看。

  • Go 不是一個純面向對象的編程語言,它不支持 class 類型。因此通過在一個類型上建立方法來實現與 class 相似的行為。
  • 同名方法可以定義在不同的類型上,但是 Go 不允許同名函數。假設我們有一個 Square 和 Circle 兩個結構體。在 Square 和 Circle 上定義同名的方法是合法的,比如下面的程序:
package main

import (  
    "fmt"
    "math"
)

type Rectangle struct {  
    length int
    width  int
}

type Circle struct {  
    radius float64
}

func (r Rectangle) Area() int {  
    return r.length * r.width
}

func (c Circle) Area() float64 {  
    return math.Pi * c.radius * c.radius
}

func main() {  
    r := Rectangle{
        length: 10,
        width:  5,
    }
    fmt.Printf("Area of rectangle %d\n", r.Area())
    c := Circle{
        radius: 12,
    }
    fmt.Printf("Area of circle %f", c.Area())
}

程序的輸出為:

Area of rectangle 50  
Area of circle 452.389342  

定義非結構體類型的方法

現在我們定義的都是結構體類型的方法。同樣可以定義非結構體類型的方法,不過這里需要注意一點。為了定義某個類型的方法,接收者類型的定義與方法的定義必須在同一個包中。目前為止,我們定義的結構體和相應的方法都是在main包中的,因此沒有任何問題。

package main

func (a int) add(b int) {  
}

func main() {

}

在上面的程序中,第3行我們試圖添加一個方法 add 給內置類型 int。這是不允許的,因為定義方法 add 所在的包和定義類型 int 的包不是同一個包。這個程序將會報編譯錯誤:cannot define new methods on non-local type int

使其工作的方法為定義內置類型的別名,然后以這個新類型為接收者創建方法。

package main

import "fmt"

type myInt int

func (a myInt) add(b myInt) myInt {  
    return a + b
}

func main() {  
    num1 := myInt(5)
    num2 := myInt(10)
    sum := num1.add(num2)
    fmt.Println("Sum is", sum)
}

上面的程序中,第5行,我們創建了新的類型,一個 int 的別名 myInt。在第7行,我們定義了一個方法 add,以 myInt作為接收者。

程序的輸出為: Sum is 15


免責聲明!

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



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