反射,嗯...,就是反著的意思唄,就是把東西反過來。
例如這樣的一個很簡單的程式碼。
var a int = 3 fmt.Println(a)
我們當然知道a
變數是int
類型,但是反過來想,程式是怎麼知道a
是 int
類型呢? ? ?
這時候,就需要用到反射了。
範例程式碼
v := reflect.TypeOf(a) fmt.Println(v)
#兩次程式碼綜合一塊執行結果
第二次的第2行程式碼,成功的將變數a
#還原出了##int 類型。
什麼? ? ?你為我有什麼用? ? ? ,嗯。 。 。實話實說,用的不是太多,但是必須會的。
在Go中,任何變數,都有具體類型和#特定值,就像 var a int = 3,#具體型別就是int
,具體值#就是3
#。
所以,變數的具體類型歸屬在reflect.Type
,變數的具體值歸屬在reflect.Value
。
並且Go的提供了
#reflect.TypeOf
#reflect.TypeOf
具體類型。 reflect.ValueOf
。 TypeOf#TypeOf
方法可以取得變數的
具體類型#########。 ############有一個這樣的需求,定義一個函數,可以接收任意類型數據,透過反射來列印變數類型。 ######func reflectType(x interface{}) { v := reflect.TypeOf(x) fmt.Printf("你传入的变量类型是:%v\n",v) }
func main() { var a int = 666 var b float64 = 3.14 var c string = "hello world" var d [3]int = [3]int{1,2,6} var e []int = []int{1,2,6,88} var f map[string]interface{} = map[string]interface{}{ "Name":"张三", "Age":18, } reflectType(a) reflectType(b) reflectType(c) reflectType(d) reflectType(e) reflectType(f) }
通过reflect.TypeOf
方法,完美解决上述需求。
这个是啥意思呢??这个在结构体中比较好体现。
简答来说就是TypeOf
返回的太笼统了,还有更加细化的类型,通过这俩属性获取。
func reflectType(x interface{}) { v := reflect.TypeOf(x) fmt.Printf("你传入的变量类型是:%v | Name:%v | Kind:%v\n", v, v.Name(), v.Kind()) }
type Student struct { Name string Age int }
func main() { var a int var b *int var c []int var d map[string]interface{} var e Student reflectType(a) reflectType(b) reflectType(c) reflectType(d) reflectType(e) }
经过对比,会发现几个特殊问题。
如果变量是指针类型,Name
为空,Kind
是ptr
。
如果變數是引用類型(切片和map)類型,Name
#為空,只有Kind
。
如果變數是#結構體#,Name
#是結構體名,Kind
是struct
。
TypeOf
只能反過來取得變數的具體類型,但是並不能取得具體值,這就有點不太厚道了。
所以ValueOf
就来解决这个问题了,但是ValueOf
牛叉的是,它里面还包括了变量类型。
注:ValueOf
和TypeOf
的Kind
属性返回内容是一摸一样的。
需求:定义一个函数,可以接收任意类型,通过反射得出变量类型和变量值。
func reflectType(x interface{}) { v := reflect.ValueOf(x) k := v.Kind() switch k { case reflect.Int: fmt.Printf("我是Int类型,我的值是%v\n",v.Int()) case reflect.Slice: fmt.Printf("我是切片类型,我的值是%v\n",v.Slice(1,2)) case reflect.Map: fmt.Printf("我是切片类型,我的值是%v\n",v.MapKeys()) //case :可以继续case下去 } }
func main() { var a int = 1 var c []int = []int{1, 5, 7, 19} var d map[string]interface{} = map[string]interface{}{ "Name": "你好", "Age": 18, } var e Student reflectType(a) reflectType(c) reflectType(d) reflectType(e) }
反射还有一个用途,就是动态的修改变量值,可能你暂时体会不到,但是语法还是要学的。
通过反射设置值,需要用到Elem
方法,并且传入的必须是指针。
示例代码
func reflectSetValue(x interface{}) { v := reflect.ValueOf(x) //kind也必须是Elem调用 var k = v.Elem().Kind() switch k { case reflect.Int: //反射修改必须通过Elem v.Elem().SetInt(200) } }
func main() { var a int = 10 fmt.Printf("a的值:%v\n", a) //反射修改值传入的必须是地址 reflectSetValue(&a) fmt.Printf("a的值:%v\n", a) }
上述我們學習了Go基礎反射的TypeOf
, TypeOf的Name和Kind
,#ValueOf
透過反射設定值
。
其中Kind
#在Type
#和ValueOf
#中都有,通常是TypeOf
##和ValueOf一起使用效果更佳!
反射這一塊,可能沒那麼好理解,一定要多下功夫!堅持! !
以上是一篇文章教你Go語言基礎之反射的詳細內容。更多資訊請關注PHP中文網其他相關文章!