Golang 反射(Reflect)

先推荐一篇讲reflect讲的不错的文章: https://blog.golang.org/laws-of-reflection

反射可以让我们在运行时检查变量的状态。golang 提供了反射的包 reflect

1.基本操作 reflect.TypeOf & reflect.ValueOf

reflect.TypeOf 返回 reflect.Type 类型:

package main

import (

"fmt"

"reflect"

)

func main() {

var x float64 = 3.4

fmt.Println("type:", reflect.TypeOf(x)) // 输出:type: float64

}

reflect.ValueOf 返回 reflect.Value 类型,该类型下有很多方法可以使用:

var x float64 = 3.4

v := reflect.ValueOf(x)

fmt.Println("type:", v.Type())

fmt.Println("kind is float64:", v.Kind() == reflect.Float64)

fmt.Println("value:", v.Float())

输出为:

type: float64

kind is float64: true

value: 3.4

2.将 reflect.Value 转换为 interface{}

通过上文的方法得到 reflect.Value 类型之后,我们还可以将该类型再转换回 interface{} 类型:

var x float64 = 3.4

v := reflect.ValueOf(x)

fmt.Println(v.Interface())

3.修改 reflect.Value

reflect.Value 类型还有对应的修改方法,但是,下面的写法会报 panic:

var x float64 = 3.4

v := reflect.ValueOf(x)

v.SetFloat(7.1) // Error: will panic.

其实,我们可以通过 CanSet() 方法来判断是否能修改:

var x float64 = 3.4

v := reflect.ValueOf(x)

fmt.Println("settability of v:", v.CanSet()) // false

那么这里为什么不能修改呢?其实就和函数传值类似,当我们进行值传递而不是引用传递时,就算在函数内部修改了变量,对外部调用者来说也是不可见的,这里的 reflect.Value 也是同理,它创建了对一个原始值的拷贝而不是引用,所以直接修改 reflect.Value 并不能对原始值产生影响。

正确的修改方法是使用引用创建 reflect.Value

var x float64 = 3.4

p := reflect.ValueOf(&x) // Note: take the address of x.

fmt.Println("type of p:", p.Type()) // *float64

fmt.Println("settability of p:", p.CanSet()) // false

v := p.Elem()

fmt.Println("settability of v:", v.CanSet()) // true

v.SetFloat(7.1) // 还有SetString, SetInt...

fmt.Println(x) // x已经被修改为7.1了

以上是 Golang 反射(Reflect) 的全部内容, 来源链接: utcz.com/z/264523.html

回到顶部