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