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了
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: Golang Interface 接口
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论