一篇文章教會(huì)你Go語言基礎(chǔ)之結(jié)構(gòu)體反射
回復(fù)“Go語言”即可獲贈(zèng)從入門到進(jìn)階共10本電子書
四月南風(fēng)大麥黃,棗花未落桐葉長(zhǎng)。
前言
Hey,大家好呀,我是碼農(nóng),星期八。
反射在結(jié)構(gòu)體中的應(yīng)用,才是最廣泛的!畢竟在Go中,是用結(jié)構(gòu)體代替對(duì)象的!
所以最多的,最麻煩的,也是反射結(jié)構(gòu)體,也是最靈活的!
反射在結(jié)構(gòu)體的應(yīng)用
上次講的,只是在普通變量中的應(yīng)用,相對(duì)來說,使用的場(chǎng)景不是太多。
但是反射在結(jié)構(gòu)體中的應(yīng)用,基本會(huì)貫穿整個(gè)Go語言基礎(chǔ)。
示例代碼
結(jié)構(gòu)體
type Student struct {Name string `json:"name" describe:"姓名"`Age int `json:"age" describe:"年齡"`Gender bool `json:"gender" describe:"性別"`Hobby []string `json:"hobby" describe:"愛好"`}
main
func main() {//實(shí)例化結(jié)構(gòu)體var s1 = Student{Name: "張三",Age: 18,Gender: true,Hobby: []string{"吃", "喝", "pia", "玩"},}var t = reflect.TypeOf(s1)fmt.Println(t.Name()) //Studentfmt.Println(t.Kind()) //structfmt.Println(t.NumField()) //結(jié)果:4,表示多少個(gè)字段for i := 0; i < t.NumField(); i++ {field := t.Field(i)//每個(gè)結(jié)構(gòu)體對(duì)象/*{Name string json:"name" describe:"姓名" 0 [0] false}{Age int json:"age" describe:"年齡" 16 [1] false}{Gender bool json:"gender" describe:"性別" 24 [2] false}{Hobby []string json:"hobby" describe:"愛好" 32 [3] false}*///fmt.Println(field)fmt.Println("------")fmt.Printf("field.Name:%v\n",field.Name)fmt.Printf("field.Index:%v\n",field.Index)fmt.Printf("field.Type:%v\n",field.Type)fmt.Printf("field.Tag:%v\n",field.Tag.Get("describe"))}}
執(zhí)行結(jié)果

單獨(dú)反射指定字段信息
main代碼
func main() {//實(shí)例化結(jié)構(gòu)體var s1 = Student{Name: "張三",Age: 18,Gender: true,Hobby: []string{"吃", "喝", "pia", "玩"},}var t = reflect.TypeOf(s1)genderField, ok := t.FieldByName("Gender")if ok {fmt.Println(genderField.Name) //Genderfmt.Println(genderField.Index) //[2]fmt.Println(genderField.Type) //boolfmt.Println(genderField.Tag.Get("describe")) //性別}}
ValueOf
上述的代碼只能用的是TypeOf,只能返回類型等信息,相對(duì)來說不是太智能,ValueOf可以獲取值,同樣也能獲取類型,相對(duì)來說比TypeOf好一點(diǎn)。
示例代碼
main
func main() {//實(shí)例化結(jié)構(gòu)體var s1 = Student{Name: "張三",Age: 18,Gender: true,Hobby: []string{"吃", "喝", "pia", "玩"},}var v = reflect.ValueOf(s1)for i := 0; i < v.NumField(); i++ {field :=v.Field(i)fmt.Println("------")fmt.Printf("Kind:%v\n",field.Kind())fmt.Printf("值:%v\n",field.Interface())}}
執(zhí)行結(jié)果

反射方法
上述我們反射的都是值,有沒有反射是否可以反射函數(shù),并且調(diào)用函數(shù)呢??
結(jié)構(gòu)體和綁定函數(shù)代碼
type Student struct {Name string `json:"name" describe:"姓名"`Age int `json:"age" describe:"年齡"`Gender bool `json:"gender" describe:"性別"`Hobby []string `json:"hobby" describe:"愛好"`}//無參方法func (this Student) Say() {fmt.Printf("我是%v,我的年齡是%v,我的性別是%v,我的愛好是%v\n", this.Name, this.Age, this.Gender, this.Hobby)}//有參數(shù)方法func (this Student) Jump(distance int) {fmt.Printf("我是%v,我跳遠(yuǎn)跳了%v米\n", this.Name, distance)}
main
func main() {//實(shí)例化結(jié)構(gòu)體var s1 = Student{Name: "張三",Age: 18,Gender: true,Hobby: []string{"吃", "喝", "pia", "玩"},}var t = reflect.TypeOf(s1)var v = reflect.ValueOf(s1)fmt.Println(v.NumMethod(),v.NumField())for i := 0; i < v.NumMethod(); i++ {method := v.Method(i)fmt.Println("--------")fmt.Println(method)//0x48c4e0 函數(shù)地址fmt.Println(method.Type())//func(int) 函數(shù)類型,形參和返回值fmt.Println(t.Method(i).Name)//Jump,函數(shù)名,注意,由t來調(diào)用的}}
執(zhí)行結(jié)果

反射調(diào)用函數(shù)
func main() {//實(shí)例化結(jié)構(gòu)體var s1 = Student{Name: "張三",Age: 18,Gender: true,Hobby: []string{"吃", "喝", "pia", "玩"},}var v = reflect.ValueOf(s1)//通過反射調(diào)用函數(shù)//調(diào)用Jump函數(shù)//反射調(diào)用函數(shù)必須傳一個(gè)參數(shù),不管有沒有形參都要傳//var args = []reflect.Value{}//v.MethodByName("Say").Call(args)//如果需要傳參數(shù)//參數(shù)需要用reflect.ValueOf(1) 強(qiáng)轉(zhuǎn)一下var args = []reflect.Value{reflect.ValueOf(2)}v.MethodByName("Jump").Call(args)}
注:注意第14行和20行代碼區(qū)別,如果要傳參數(shù),參考第20行代碼。
執(zhí)行結(jié)果

反射注意事項(xiàng)
在平常開發(fā)中,盡量慎用反射,原因如下。
反射性能可能會(huì)比較低,畢竟是反正走的,一般比正向操作慢一兩個(gè)級(jí)別。
反射越多,代碼越爛,
TypeOf和ValueOf都有Kind,很多情況是TypeOf和ValueOf混用的,所以對(duì)于基礎(chǔ)不好的,極不友好。在Go中,是沒有
try的,如果反射沒有處理好異常,程序會(huì)直接崩潰,可能在意想不到的地方。
總結(jié)
上述我們主要講述了Go反射結(jié)構(gòu)體的相關(guān)知識(shí),包括有
反射在結(jié)構(gòu)體中的應(yīng)用
如何單獨(dú)反射結(jié)構(gòu)體字段信息
ValueOf其他操作
如何放射結(jié)構(gòu)體綁定的方法
到此為止反射就講完了,一定要多嘗試,多敲敲代碼,反射的用法還有很多。
如果在操作過程中有任何問題,記得下面留言,我們看到會(huì)第一時(shí)間解決問題。我是碼農(nóng)星期八,如果覺得還不錯(cuò),記得動(dòng)手點(diǎn)贊一下哈。感謝你的觀看。
想了解更多關(guān)于Go的知識(shí),請(qǐng)前往:http://pdcfighting.com/
-------------------?End?-------------------
往期精彩文章推薦:

歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持
想加入Go學(xué)習(xí)群請(qǐng)?jiān)诤笈_(tái)回復(fù)【入群】
萬水千山總是情,點(diǎn)個(gè)【在看】行不行
