<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
反射指的是執行時動態的獲取變數的相關資訊
型別是變數,類別是常數
reflect.TypeOf,獲取變數的型別,返回reflect.Type型別
reflect.ValueOf,獲取變數的值,返回reflect.Value型別
reflect.Value.Kind,獲取變數的類別,返回一個常數
reflect.Value.Interface(),轉換成interface{}型別
package main import ( "fmt" "reflect" ) func Test(i interface{}) { //反射資料型別 t := reflect.TypeOf(i) fmt.Println("型別是", t) //反射資料值 v := reflect.ValueOf(i) fmt.Println("值是", v) } func main() { a := "hello" Test(a) }
輸出結果如下
型別是 string
值是 hello
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 } func Test(i interface{}) { //反射獲取型別 t := reflect.TypeOf(i) fmt.Println("型別是", t) //反射獲取值 v := reflect.ValueOf(i) //判斷值的類別 c := v.Kind() fmt.Println("類別是", c) } func main() { var stu Student = Student{ Name: "張三", Age: 18, Score: 80, } Test(stu) fmt.Println("-------------") var num int = 10 Test(num) }
輸出結果如下
型別是 main.Student
類別是 struct
-------------
型別是 int
類別是 int
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 } func Test(i interface{}) { t := reflect.TypeOf(i) fmt.Println("型別是", t) //類別 v := reflect.ValueOf(i) c := v.Kind() fmt.Println("類別是", c) fmt.Printf("c的型別是%Tn", c) fmt.Printf("v的型別是%Tn", v) //轉換成介面 iv := v.Interface() fmt.Printf("iv的型別%Tn", iv) //斷言處理 stu_iv, err := iv.(Student) if err { fmt.Printf("stu_iv的型別%Tn", stu_iv) } } func main() { var stu Student = Student{ Name: "張三", Age: 18, Score: 80, } Test(stu) }
輸出結果如下
型別是 main.Student
類別是 struct
c的型別是reflect.Kind
v的型別是reflect.Value
iv的型別main.Student
stu_iv的型別main.Student
reflect.valueof(x).Float()
reflect.valueof(x).Int()
reflect.valueof(x).String()
reflect.Valueof(x).Bool()
package main import ( "fmt" "reflect" ) func Test(i interface{}) { v := reflect.ValueOf(i) fmt.Printf("v的型別是%Tn", v) //轉換成指定型別 t := v.Int() fmt.Printf("t的型別是%Tn", t) } func main() { //型別不同的話會報錯 var num int = 100 Test(num) }
輸出結果如下
v的型別是reflect.Value
t的型別是int64
reflect.Value.SetFloat(),設定浮點數
reflect.value.SetInt(),設定整數
reflect.Value.SetString(),設定字串
package main import ( "fmt" "reflect" ) func Test(i interface{}) { v := reflect.ValueOf(i) //更新值需要value的地址,否則會儲存,Elem()表示指標* v.Elem().SetInt(100) result := v.Elem().Int() fmt.Printf("result型別為 %T, 值為 %dn", result, result) } func main() { var num int = 10 Test(&num) }
輸出結果如下
result型別為 int64, 值為 100
反射出結構體的屬性和方法數量
方法名需大寫,需要被跨包呼叫識別
package main import ( "fmt" "reflect" ) //結構體 type Student struct { Name string Age int Score float32 } //結構體方法 func (s Student) Run() { fmt.Println("Running") } func (s Student) Sleep() { fmt.Println("Sleeping") } //使用反射檢視結構體欄位數量和方法數量 func Test(i interface{}) { v := reflect.ValueOf(i) //類別判斷 if v.Kind() != reflect.Struct { fmt.Println("不是結構體") return } //獲取結構體中欄位數量 stu_num := v.NumField() fmt.Println("欄位數量: ", stu_num) //獲取結構體中方法數量 stu_meth := v.NumMethod() fmt.Println("方法數量: ", stu_meth) } func main() { var stu Student = Student{ Name: "張三", Age: 18, Score: 88, } Test(stu) }
輸出結果如下
欄位數量: 3
方法數量: 2
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 } func Test(i interface{}) { v := reflect.ValueOf(i) //獲取結構體中每個屬性 for i := 0; i < v.NumField(); i++ { //輸出屬性值 fmt.Printf("%d %vn", i, v.Field(i)) //輸出屬性值的型別 fmt.Printf("%d %vn", i, v.Field(i).Kind()) } } func main() { var stu Student = Student{ Name: "張三", Age: 18, Score: 88, } Test(stu) }
輸出結果如下
0 張三
0 string
1 18
1 int
2 88
2 float32
package main import ( "fmt" "reflect" ) type Student struct { Name string Age int Score float32 } func Test(i interface{}, name string) { v := reflect.ValueOf(i) vk := v.Kind() //判斷是都為指標並指向結構體型別 if vk != reflect.Ptr && v.Elem().Kind() == reflect.Struct { fmt.Println("expect struct") return } //更改屬性值 v.Elem().Field(0).SetString(name) //獲取結構體中每個屬性 for i := 0; i < v.Elem().NumField(); i++ { //輸出屬性值 fmt.Printf("%d %vn", i, v.Elem().Field(i)) //輸出屬性值的型別 fmt.Printf("%d %vn", i, v.Elem().Field(i).Kind()) } } func main() { var stu Student = Student{ Name: "張三", Age: 18, Score: 88, } Test(&stu, "李四") }
輸出結果如下
0 李四
0 string
1 18
1 int
2 88
2 float32
package main import ( "encoding/json" "fmt" "reflect" ) type Student struct { Name string `json:"stu_name"` Age int Score float32 } func Test(i interface{}, name string) { v := reflect.ValueOf(i) vk := v.Kind() //判斷是都為指標並指向結構體型別 if vk != reflect.Ptr && v.Elem().Kind() == reflect.Struct { fmt.Println("expect struct") return } //更改屬性值 v.Elem().Field(0).SetString(name) //獲取結構體中每個屬性 for i := 0; i < v.Elem().NumField(); i++ { //輸出屬性值 fmt.Printf("%d %vn", i, v.Elem().Field(i)) //輸出屬性值的型別 fmt.Printf("%d %vn", i, v.Elem().Field(i).Kind()) } } func main() { var stu Student = Student{ Name: "張三", Age: 18, Score: 88, } Test(&stu, "李四") fmt.Println("----------------json原資訊----------------") result, _ := json.Marshal(stu) fmt.Println("json原資訊: ", string(result)) //反射獲取型別 st := reflect.TypeOf(stu) s := st.Field(0) fmt.Printf("Name原資訊名稱: %sn", s.Tag.Get("json")) }
輸出結果如下
0 李四
0 string
1 18
1 int
2 88
2 float32
----------------json原資訊----------------
json原資訊: {"stu_name":"李四","Age":18,"Score":88}
Name原資訊名稱: stu_name
Go 中函數是可以賦值給變數的
範例:
既然函數可以像普通的型別變數一樣,那麼在反射機制中就和不同的變數是一樣的,在反射中函數和方法的型別(Type)都是reflect.Func
,如果要呼叫函數,通過 Value
的Call()
方法
package main import ( "fmt" "reflect" ) func hello() { fmt.Println("hello world") } func main() { //反射使用函數 v := reflect.ValueOf(hello) //型別判斷是否屬於reflect.func型別 if v.Kind() == reflect.Func { fmt.Println("函數") } //反射呼叫函數 v.Call(nil) //Call中需要傳入的是切片 }
輸出結果如下
函數
hello world
package main import ( "fmt" "reflect" "strconv" ) //反射呼叫傳參和返回值函數 func Test(i int) string { return strconv.Itoa(i) } func main() { v := reflect.ValueOf(Test) //定義引數切片 params := make([]reflect.Value, 1) //切片元素賦值 params[0] = reflect.ValueOf(20) //反射調函數 result := v.Call(params) fmt.Printf("result的型別是 %Tn", result) //[]reflect.Value切片轉換string s := result[0].Interface().(string) fmt.Printf("s的型別是 %T ,值為 %sn", s, s) }
輸出結果如下
result的型別是 []reflect.Value
s的型別是 string ,值為 20
反射中方法的呼叫,函數和方法可以說其實本質上是相同的,只不過方法與一個“物件”進行了“繫結”,方法是“物件”的一種行為,這種行為是對於這個“物件”的一系列操作,例如修改“物件”的某個屬性
package main import ( "fmt" "reflect" "strconv" ) //反射方法 type Student struct { Name string Age int } //結構體方法 func (s *Student) SetName(name string) { s.Name = name } func (s *Student) SetAge(age int) { s.Age = age } func (s *Student) String() string { return fmt.Sprintf("%p", s) + ",Name:" + s.Name + ",Age:" + strconv.Itoa(s.Age) } func main() { //範例化 stu := &Student{"張三", 19} //反射獲取值:指標方式 stuV := reflect.ValueOf(&stu).Elem() fmt.Println("修改前: ", stuV.MethodByName("String").Call(nil)[0]) //修改值 params := make([]reflect.Value, 1) //定義切片 params[0] = reflect.ValueOf("李四") stuV.MethodByName("SetName").Call(params) params[0] = reflect.ValueOf(20) stuV.MethodByName("SetAge").Call(params) fmt.Println("修改後: ", stuV.MethodByName("String").Call(nil)[0]) }
輸出結果如下
修改前: 0xc000004078,Name:張三,Age:19
修改後: 0xc000004078,Name:李四,Age:20
package main import ( "fmt" "reflect" "strconv" ) //反射方法 type Student struct { Name string Age int } //結構體方法 func (s *Student) B(name string) { s.Name = name } func (s *Student) A(age int) { s.Age = age } func (s *Student) C() string { return fmt.Sprintf("%p", s) + ",Name:" + s.Name + ",Age:" + strconv.Itoa(s.Age) } func main() { //範例化 stu := &Student{"張三", 19} //反射獲取值:指標方式 stuV := reflect.ValueOf(&stu).Elem() //索引呼叫方法 fmt.Println("修改前: ", stuV.Method(2).Call(nil)[0]) params := make([]reflect.Value, 1) params[0] = reflect.ValueOf("李四") stuV.Method(1).Call(params) params[0] = reflect.ValueOf(20) stuV.Method(0).Call(params) fmt.Println("修改後: ", stuV.Method(2).Call(nil)[0]) //呼叫索引大小取決於方法名稱的ASCII大小進行排序 }
輸出結果如下
修改前: 0xc000004078,Name:張三,Age:19
修改後: 0xc000004078,Name:李四,Age:20
到此這篇關於Go語言學習之反射的用法詳解的文章就介紹到這了,更多相關Go語言反射內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45