Go 語言中的方法(第一部分)

來源:互聯網
上載者:User
Golang 程式中定義的類型有與其相關的方法。讓我們來看一個例子:```gotype T struct { name string}func (t T) PrintName() { fmt.Println(t.name)}func main() { t := T{name: "Michał"} t.PrintName()}```正如您可能懷疑程式輸出名字。方法是一個函數,擁有附加的,單獨元素的參數列表,稱之為接收器。它被放在一個方法名之前。接收器的類型決定了如何使用方法。## 接收器方法被綁定到接收器的基類。小例子解釋的很好:```gotype T struct { name string}func (T) F() {}func (*T) F() {}```上面的代碼無法編譯. 第一個 F 方法被綁到 T 上. 第二各方法被邦到 *T 上. 對於單個基底類型,方法名必須唯一,所以編譯將報錯:```> go install github.com/mlowicki/lab && ./spec/bin/lab# github.com/mlowicki/labspec/src/github.com/mlowicki/lab/lab.go:103: method redeclared: T.F method(T) func() method(*T) func()```如果基類是一個 struct 類型,那麼欄位名不能和方法名重複。```gotype T struct { M int}func (t T) M() {}```編譯失敗資訊如下:```type T has both field and method named M```Go 的類型系統限制了哪些類型可以作為接收器. 它不能是介面類型或指標,因此它不可能為一個空介面(interface{})定義方法來滿足所有類型。 只允許使用類型名稱,所以,類型字面值會導致編譯錯誤:```gofunc (v map[string]float64) M() {}```錯誤資訊 `invalid receiver type map[string]float64 (map[string]float64 is an unnamed type).`## 方法集調用一個 T 類型的變數上的 m 方法, 方法 m 必須在與 T 關聯的方法集上. 方法集中的一個成員是什麼意思?### 介面類型介面類型的方法集是介面自己 — 為實現介面需要定義方法列表:```gotype I interface { F() G()}type T struct{}func (T) F() {}func (T) G() {}func (T) H() {}func main() { var i I = T{} i.F() i.G() i.H() // error: i.H undefined (type I has no field or method H)}```上面的例子中,不允許調用 T 類型的變數 i 上的方法。僅有來自介面的介面類型值方法屬於介面類型的方法集。(方法集是靜態,當分配不同類型的值時不會改變)。 要調用 H 方法,需要先使用類型斷言:```got, ok := i.(T)if !ok { log.Fatal("Type assertion failed")}t.H()```### 非介面類型對於非介面類型 T,方法集由接收器為 T 的方法組成:```gotype T struct{}func (T) F() {}func (T) G() {}type U struct{}func (U) H() {}func main() { t := T{} t.F() t.G() t.H() // error: t.H undefined (type T has no field or method H)}```當處理 T 類型的指標時, 它的方法集由接收器為 T 或 *T 的方法組成:```gotype T struct{}func (T) F() {}func (T) G() {}func (*T) H() {}func main() { t := &T{} t.F() t.G() t.H()}```為什麼 T 的方法集沒有 *T 類型接收器的方法,而 *T 的方法集卻包含 T 類型接收器的方法呢? 令人驚訝的是,分配給 t 不是地址,但無指標結構值仍執行的很好:```got := T{}t.F()t.G()t.H()```Go 規範描述了明確的情況:> 如果 x 是可定址的,並且 x 的方法集包含 m ,x.M() 是 (&x).M() 的速記。何時使用值還是指標接收器的建議放在了官方的 [FAQ](https://golang.org/doc/faq#methods_on_values_or_pointers)中。### 唯一性類型 T 定義的方法集不能有倆個名字一樣的方法。 有相同的方法名但不同類型的參數,在 Go 中是不可能的。 ( Go 中沒有 [ad hoc polymorphism](https://en.wikipedia.org/wiki/Ad_hoc_polymorphism) )。> 類型 T 定義的方法集由 T 實現.## 列印方法集Go 有 [reflect](https://golang.org/pkg/reflect/) 包,對於看類型的方法集很有用:```gofunc PrintMethodSet(val interface{}) { t := reflect.TypeOf(val) fmt.Printf("Number of methods: %d\n", t.NumMethod()) for i := 0; i < t.NumMethod(); i++ { m := t.Method(i) fmt.Printf("Method %s\n", m) fmt.Printf("\tName: %s\n", m.Name) fmt.Printf("\tPackage path: %s\n", m.PkgPath) }}```從 [Method](https://golang.org/pkg/reflect/#Value.Method) 傳回值類型,方法是 [Method](https://golang.org/pkg/reflect/#Method) 類型.值得一提的是,文檔有個 bug, 因為 [NumMethod](https://golang.org/pkg/reflect/#Value.NumMethod) 從方法集返回了方法的數量,但只有那些被匯出的方法 (名字以大寫字母開頭)。 歸檔在 [#17686](https://github.com/golang/go/issues/17686).## 引入類型方法方法只能被定義在有類型建立的包裡。github.com/mlowicki/lib/lib.go:```gopackage libtype T struct{}```github.com/mlowicki/lab/lab.go:```gopackage mainimport ( "fmt" . "github.com/mlowicki/lib")func (T) F() {}func (*T) F() {}[...]```這會引起構建錯誤 `cannot define new methods on non-local type lib.T`.## 不使用參數函數/方法定義不強制命名所有參數或接收者。如果不使用它們,則只能指定類型。 Name can be eventually introduced later on when it’ll actually needed:```gotype T struct { name string}func (t T) F(name string) {}func (T) G(string) {}```G 的聲明省略無用標識符。

via: https://medium.com/golangspec/methods-in-go-part-i-a4e575dff860

作者:Michał Łowicki 譯者:themoonbear 校對:polaris1119

本文由 GCTT 原創編譯,Go語言中文網 榮譽推出

本文由 GCTT 原創翻譯,Go語言中文網 首發。也想加入譯者行列,為開源做一些自己的貢獻嗎?歡迎加入 GCTT!
翻譯工作和譯文發表僅用於學習和交流目的,翻譯工作遵照 CC-BY-NC-SA 協議規定,如果我們的工作有侵犯到您的權益,請及時聯絡我們。
歡迎遵照 CC-BY-NC-SA 協議規定 轉載,敬請在本文中標註並保留原文/譯文連結和作者/譯者等資訊。
文章僅代表作者的知識和看法,如有不同觀點,請樓下排隊吐槽

146 次點擊  
相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.