Go語言的方法

2021-09-10 15:07:38 字數 2684 閱讀 7307

目錄

方法概述

巢狀結構體中的方法呼叫

方法變數

方法表示式 封裝

儘管go沒有統一的物件導向程式設計(oop)的定義,但依然支援方法(c++中常叫做成員函式)。因為對我們來說,物件就是乙個值或變數,並且擁有其方法,而方法是某種特定型別的函式。oop就是使用方法來描述每個資料結構的屬性和操作。

go語言的方法宣告和普通函式宣告類似,只是在函式名前面多了乙個引數。這個引數把這個方法繫結到這個引數對應的型別上。如下所示:

type point struct 

func (p *point) distance(q *point) float64

附加的引數稱為方法的接收者,接收者的零值為nil。在go語言中,接收者不適用特殊名(如c++的this或者python的self),而是允許我們自主決定接收者的名字。由於方法會複製每乙個實參變數,如果需要更新乙個成員變數,或者如果乙個實參太大而我們希望避免複製整個實參,通常使用指標來傳遞變數的位址,這也適用於更新接收者。

go和許多其他物件導向的語言不同,go允許將方法繫結到任何型別上,因此可以很方便地為簡單的型別(數字、字串、slice、map,甚至是函式等)定義附加的行為。同乙個包下的任何型別都可以宣告方法,只要它的型別既不是指標型別也不是介面型別。如下:

type path point

func (path *path) distance float64

}return sum

}

巢狀結構體中,型別是外層結構體(或其指標)的接收者可以呼叫型別是內嵌結構體(或其指標)的方法。但不同於其他物件導向語言,型別是內層結構體的變數並不能轉換為外層結構體型別,反之也不能。而在c++中基類指標被允許指向派生類物件。

import "image/color"

type coloredpoint struct

func main() , color.rgba}

q := coloredpoint, color.rgba}

fmt.println(p.distance(q.point))

}

如果考慮具體實現,內嵌欄位會告訴編譯器生成額外的包裝方法來呼叫point宣告的方法,這相當於以下**:

func (p *coloredpoint) distance(q *point) float64
方法也是函式,因此函式變數的概念也適用於方法。通常我們都在相同的表示式中使用和呼叫方法,但把兩個操作分開也是可以的。如下所示,呼叫時只需要提供實參而不需要提供接收者就能夠呼叫:

package main

import (

"fmt"

"math"

)type point struct

func (p *point) distance(q *point)

func main()

q := point

distancefromp := p.distance //方法變數

fmt.printf("%t\n", distancefromp) //輸出 func(*main.point)float64

fmt.println(distancefromp(&q)) //輸出 5

}

如果包內的api呼叫乙個函式值,並且使用者希望這個函式的行為是呼叫乙個特定接收者的方法,方法變數就非常有用。 

和呼叫乙個函式不同,在呼叫方法時必須提供接收者,並且按照選擇子的語法進行呼叫。而方法表示式寫成t.f或者(*t).f,其中t是型別,是一種函式變數,把原來方法的接收者替換成函式的第乙個形參,因此它可以像平常的函式一樣呼叫。

p := point

q := point

distance := (*point).distance

fmt.printf("%t\n%g\n", distance, distance(&p, &q))

//輸出func(*main.point,*main.point) float64 和 5

如果你需要乙個值來代表多個方法中的乙個,而方法都屬於同乙個型別,方法表示式可以幫助你呼叫這個值所對應的方法來處理不同的接收者。

type point struct 

func (p point) add(q point) point

}func (p point) sub(q point) point

}type path point

func (path path) translateby(offset point, add bool) else

for i := range path

}

上面**中,add方法和sub方法的接收者、形參和返回值的型別都相同,因此可以借助方法表示式來統一表示乙個變數型別,從而根據需要呼叫不同的方法。 

go語言只有一種方式控制命名的可見性:定義的時候,首字母大寫的識別符號是可以從包中匯出的,而首字母沒有大寫的則不可匯出。同樣的機制也適用於結構體內的字段和型別中的方法。因此在go語言中要封裝乙個物件,必須使用結構體。

此外,在go語言中封裝的單元是包而不是型別。無論是在函式內的**還是方法內的**,結構體型別內的字段對於同乙個包中的所有**都是可見的。

本文部分內容摘自《go程式語言》,有改動

go語言 方法

go 語言中沒有類,但是是有方法。方法的定義 func recevier type methodname 引數列表 返回值列表 type school struct func newschool name,addr string school func s school getname string...

Go 語言函式方法

go 語言中同時有函式和方法。乙個方法就是乙個包含了接受者的函式,接受者可以是命名型別或者結構體型別的乙個值或者是乙個指標。所有給定型別的方法屬於該型別的方法集。語法格式如下 func variable name variable data type function name return typ...

GO語言 String 方法的思考

對於定於了string 方法的型別,預設輸出的時候會呼叫該方法,實現字串的列印。例如下面 package main import fmt type man struct func m man string string func main 輸出 my name is sns然而,如果使用func m...