Golang 反射个人理解

2021-05-06  本文已影响0人  Good_Nine9

(value) Elem()

如果value是空接口类型,返回其具体的值
如果是指针,返回指向的内容

(type) Elem()

如果type是array、chanel、slice,返回其元素type
如果是map,返回 v 的type
如果是指针,返回指向内容的type

Indirect()

如果是指针,返回其指向的值
如果不是指针的话,返回Elem()

func Indirect(v Value) Value {
    if v.Kind() != Ptr {
        return v
    }
    return v.Elem()
}

用反射修改一个对象的值

这里遇到了一个小坑,那就是当对象没有暴露出来的时候(首字母没有大写),会失败,出现这个错误 panic: reflect: reflect.Value.SetInt using value obtained using unexported field

type Geek struct {
    A int `tag1:"First Tag" tag2:"Second Tag"`
    B string
}

f := Geek{A: 10, B: "Number"}
fmt.Println(f)
// {10 Number}

// 必须传址,传值无法修改
fval := reflect.ValueOf(&f)

// 如果没有Elem()的话,会panic: reflect: call of reflect.Value.Field on ptr Value
fval.Elem().Field(0).SetInt(14)
fval.Elem().Field(1).SetString("fads")
fmt.Println(f)
// {14 fads}

New()

有点等同于reflect.ValueOf(&value)但是用法不一样。
要传入一个reflect.Type,构建出一个新的对象,可以set值进去。
example

type Geek struct {
    A int `tag1:"First Tag" tag2:"Second Tag"`
    B string
}

f := Geek{A: 10, B: "Number"}

// 拿到 Type
fType := reflect.TypeOf(f)
// 创建新对象
fVal := reflect.New(fType)
// 可以设置值
fVal.Elem().Field(0).SetInt(20)
fVal.Elem().Field(1).SetString("Number")

Addr()

拿到被反射对象的地址,一般是用 .Addr().Interface() 这样用的

f := Geek{A: 10, B: "Number"}
fmt.Println(uintptr(unsafe.Pointer(&f)))
// 824634400800
fval := reflect.ValueOf(&f).Elem()
s := fval.Addr().Pointer()
// 824634400800
k := fval.Addr().Interface()
fmt.Println(s == &f)
// true
上一篇 下一篇

猜你喜欢

热点阅读