首頁  >  文章  >  後端開發  >  一篇文章教你Go語言基礎之反射

一篇文章教你Go語言基礎之反射

Go语言进阶学习
Go语言进阶学习轉載
2023-07-25 17:01:581161瀏覽

什麼是反射

反射,嗯...,就是反著的意思唄,就是把東西反過來。

例如這樣的一個很簡單的程式碼。

var a int = 3
fmt.Println(a)

我們當然知道a變數是int類型,但是反過來想,程式是怎麼知道a int類型呢? ? ?

這時候,就需要用到反射了。

範例程式碼

v := reflect.TypeOf(a)
fmt.Println(v)

#兩次程式碼綜合一塊執行結果

一篇文章教你Go語言基礎之反射

第二次的第2行程式碼,成功的將變數a#還原出了##int 類型。

什麼? ? ?你為我有什麼用? ? ? ,嗯。 。 。實話實說,用的不是太多,但是必須會的。


反射(reflect套件)

在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)
}

main

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)
}

执行结果

一篇文章教你Go語言基礎之反射

通过reflect.TypeOf方法,完美解决上述需求。

TypeOf 的Name和Kind

这个是啥意思呢??这个在结构体中比较好体现。

简答来说就是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
}
main
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)
}

执行结果

一篇文章教你Go語言基礎之反射

总结

经过对比,会发现几个特殊问题。

如果变量是指针类型Name为空,Kindptr

如果變數是引用類型(切片和map)類型,Name#為空,只有Kind

如果變數是#結構體#,Name#是結構體名,Kindstruct

ValueOf

TypeOf只能反過來取得變數的具體類型,但是並不能取得具體值,這就有點不太厚道了。

所以ValueOf就来解决这个问题了,但是ValueOf牛叉的是,它里面还包括了变量类型

注:ValueOfTypeOfKind属性返回内容是一摸一样的。

需求:定义一个函数,可以接收任意类型,通过反射得出变量类型和变量值。

函数

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下去
  }
}

main

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)
}

执行结果

一篇文章教你Go語言基礎之反射

通过反射设置值

反射还有一个用途,就是动态的修改变量值,可能你暂时体会不到,但是语法还是要学的。

通过反射设置值,需要用到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)
  }
}

main

func main() {
  var a int = 10
  fmt.Printf("a的值:%v\n", a)
  //反射修改值传入的必须是地址
  reflectSetValue(&a)
  fmt.Printf("a的值:%v\n", a)
}

执行结果

一篇文章教你Go語言基礎之反射

總結

上述我們學習了Go基礎反射的TypeOfTypeOf的Name和Kind#ValueOf 透過反射設定值

其中Kind#在Type#和ValueOf#中都有,通常是TypeOf##和ValueOf一起使用效果更佳!

反射這一塊,可能沒那麼好理解,一定要多下功夫!堅持! !

以上是一篇文章教你Go語言基礎之反射的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:Go语言进阶学习。如有侵權,請聯絡admin@php.cn刪除