go reflect 取指针_Go的方法集详解
女主宣言
Go語言以其本身具有的高并發特性,在云計算開發中,得到了廣泛的應用,也深受廣大開發者的歡迎。但是大家對go語言真的了解了么?本文作者經過對go語言的多年實踐應用,現對go語言中的方法集進行了一次詳細的總結,并通過實驗進行了驗證,相信對于go語言愛好者有很大的幫助。下來就跟隨作者一起學習下吧。
PS:豐富的一線技術、多元化的表現形式,盡在“360云計算”,點關注哦!
1
什么是方法集
在go語言中,每個類型都有與之關聯的方法,把這個類型的所有方法稱為類型的方法集。如下:
type Student struct { age int8 name string} func (s Student) showName() { fmt.Println(s.name)} func (s * Student) setName(newName string) { s.name = newName}類型Student方法集包含了showName()方法。類型*Student方法集包含了showName()方法和setName()方法。為什么呢?因為:類型 T 方法集,包含全部 receiver T 方法。
類型 *T 方法集,包含全部 receiver T + *T 方法。
2
方法集和方法接受者的關系
在上面的案例中,類型Student的方法集并不包含了setName()方法,那么是不是Student類型變量,就不能調用setName()方法呢?即下面調用,是否會報錯呢?
s := Student{}s.setName("dq")其實,上面的調用是ok的。為什么呢?我們來回顧一下go語言的方法定義。- 參數 receiver 可任意命名,如方法中,不使用參數,可以省略參數名。
- 參數 receiver 類型可以是 T 或 *T,但類型T不能為接口或指針類型。
- 不支持方法重載。
- 實例value或pointer可以調用全部的方法,編譯器會自動轉換。
如下:
type Student struct { age int8 name string}type StudentPoint *Student func (Student) sayHello() { //省略receiver 的參數參數名字 fmt.Println("hello world")} func (s Student) showName() { fmt.Println(s.name)} func (s * Student) setName(newName string) { s.name = newName} func (s StudentPoint) showName2(){ // Error:接受者(receiver)為指針類型 fmt.Println(s.name)} s := Student{}s.setName("dq") //go會自動轉為 (&s).setName("dq") var s2 = &ss2.showName() //o會自動轉為 (*s2).showName()所以,當類型調用自己申明的方法的時候,不需要考慮方法集。方法接受者是值類型(T),還是指針類型(*T),影響T類型的實體變量的方法集。
3
方法集和接口
接口的定義
接口是一個或多個方法簽名的集合。任何類型的方法集中只要擁有該接口“對應的全部方法”聲名。就表示它 "實現" 了該接口,無須在該類型上顯式聲明實現了哪個接口。對應的全部方法:是指有相同名稱、參數列表 (不包括參數名) 以及返回值。接口只有方法的聲明,沒有實現。接口可以匿名嵌入到其他接口,或是嵌入結構體中。接口命名習慣以 er 結尾。type Personer interface { //定義一個接口 showName()} type Student struct { Personer //嵌入接口}接口執行機制
接口對象,是由接口表(interface table)和數據指針組成。接口表存儲元數據信息,包括接口類型、動態類型,以及實現接口的方法指針。數據指針持有的是目標對象的只讀復制品,復制完整對象或指針。package main import ( "fmt" "reflect") type User struct { id int name string} type Student struct { id int name string} func main() { u := User{1, "Tom"} var i interface{} = u // 由于interface{}不包含任何方法,所以任何類型,都實現了interface{}接口 fmt.Println(reflect.TypeOf(i)) //main.User i = Student{} fmt.Println(reflect.TypeOf(i)) //main.Student}以實體類型和以指針類型實現接口的區別
類型必須實現接口的所有方法,才能表示它 "實現" 了該接口,如下:
type Animal interface { say() doSome()} type Dog struct { name string}func (_self Dog) say() { fmt.Println("I am", _self.name)}func (_self *Dog) doSome() { fmt.Println("I will do something")} func main() { // 報錯,因為Dog的value類型實現了Animal接口的say方法沒有實現doSome方法 var d1 Animal= Dog{name:"wangCai1"} d1.say() //因為dDog 的指針類型實現了Animal接口集的所有方法 var d2 Animal= &Dog{name:"wangCai2"} d2.say() }4
方法集和嵌入
什么是嵌入
go語言中,所謂的嵌入,即把一個類型作為另外一個類型的匿名字段。如下:
type Person struct { age int8 name string} type Student struct { Person //嵌人 Persion類型}go語言通過嵌入組合,來實現繼承的行為。于是,我們就可以通過Student類型的實例,訪問Persion類型的變量和方法。如下:
var s = Student{}s.name?=?"dq"值類型(T)嵌入和指針類型(*T)嵌入的區別
type Student1 struct { Person //值類型的嵌入}type Student2 struct { *Person //指針類型的嵌入}要理解這個區別,就有知道go語言中類型的默認值。如下:- 數值類型(如int8、int16、uint等),默認值為0;
- 布爾類型,默認值為false;
- 字符串類型,默認值為""
- 指針、通道、切片、字典等,默認值為nil
- 復合類型的默認值,為所包含類型的默認值。
嵌入和方法集的關系
- 類型 S 包含匿名字段 T,則 S和*S 方法集包含 T 方法。
- 類型 S 包含匿名字段 *T,則 S和 *S 方法集包含 T + *T 方法。
- 不管嵌入的是T還是*T,*S方法集,包含 T + *T 方法。
360云計算
由360云平臺團隊打造的技術分享公眾號,內容涉及數據庫、大數據、微服務、容器、AIOps、IoT等眾多技術領域,通過夯實的技術積累和豐富的一線實戰經驗,為你帶來最有料的技術分享
總結
以上是生活随笔為你收集整理的go reflect 取指针_Go的方法集详解的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c#获取本地ip地址网关子网掩码_教你如
- 下一篇: python中将字符变为大写_Pytho