本文主要是介绍经过99次失败后, 我总结了几点 Golang 反射的经验(附源码),对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
// kind_type_test.go // 打印 kind 和 type 的值 func kind_type_value(v interface{}) { rv := reflect.ValueOf(v) fmt.Println(rv.Kind(), rv.Type()) } // kind 和 type 相同字面值 func Test_Kind_Type_Same(t *testing.T) { name := "tangxin" age := 18 kind_type_value(name) // string string kind_type_value(age) // int int kind_type_value(&name) // ptr *string kind_type_value(&age) // ptr *int }
// 根据内置类型 string 的自定义类型 type MyString string // kind 和 type 不同 func Test_KindType_Different(t *testing.T) { p := Person{ Name: "tagnxin", Age: 18, } kind_type_value(p) // struct main.Person kind_type_value(&p) // ptr *main.Person s1 := MyString("tangxin") kind_type_value(s1) // string main.MyString kind_type_value(&s1) // ptr *main.MyString }
// 第一定律: 对象类型转指针类型 func Test_Rule1(t *testing.T) { p := &Person{ Name: "zhangsan", Age: 18, Addr: struct { City string }{ City: "chengdu", }, } rule1(p) // ptr *main.Person rule1(&p) // ptr **main.Person } func rule1(v interface{}) { rv := reflect.ValueOf(v) fmt.Println(rv.Kind(), rv.Type()) }
func rule2(rv reflect.Value) { // check if !rv.CanInterface() { fmt.Println("rv is not settable: ", rv.Type()) return } // convert rv = DerefValue(rv) irv := rv.Interface() fmt.Println(irv) // type assert v, ok := irv.(Person) fmt.Println(v, ok) // {zhangsan 18 {chengdu}} true }
func rule3(rv reflect.Value) { if !rv.CanSet() { fmt.Println("rv is not settable", rv.Type()) return } switch rv.Kind() { case reflect.String: rv.SetString("tangxin") case reflect.Int: rv.SetInt(333) default: fmt.Println("not support kind: ", rv.Kind()) } }
const ( Invalid Kind = iota Bool Int // ... String // ... Interface Map Ptr // 这里是重点, 指针可以只想任何容器类型,包括指针本身。 )
func Indirect(v Value) Value { if v.Kind() != Ptr { return v } return v.Elem() }
// rule1_test.go // 指向指针的指针对象 func Test_Rule1(t *testing.T) { p := &Person{ Name: "zhangsan", Age: 18, Addr: struct { City string }{ City: "chengdu", }, } rv := reflect.ValueOf(&p) fmt.Println(rv.Kind(), rv.Type()) // ptr **main.Person }
// value.go // DerefValue 返回最底层的反射容器对象 func DerefValue(rv reflect.Value) reflect.Value { for rv.Kind() == reflect.Ptr { rv = rv.Elem() } return rv }
type student struct { Name string Age int } func (stu *student) SetDefaults() { stu.Name = "tangxin" if stu.Age == 0 { stu.Age = 100 } } // 没有传参数的方法 func (stu *student) Greeting() { fmt.Printf("hello %s, %d years old\n", stu.Name, stu.Age) } // 具有传参数的方法 func (stu *student) Aloha(name string) { fmt.Println("aloha,", name) } func Test_MethodCall(t *testing.T) { stu := student{ Name: "wangwu", } // 注意 // 方法对象的方法接收者, 可以是 **指针对象** 也可以是 **结构体对象** // 如果是指针对象的方法, **结构体对象** 是不能调用起方法的 rv := reflect.ValueOf(stu) prv := reflect.ValueOf(&stu) stu.Greeting() methodCall(prv, "SetDefaults") methodCall(rv, "Greeting") // 结构体接收者, 找不到方法 methodCall(prv, "Aloha", reflect.ValueOf("boss")) } // 对象方法调用 // rv 目标对象, method 方法名称, in 参数 func methodCall(rv reflect.Value, method string, in ...reflect.Value) { // 通过方法名称获取 反射的方法对象 mv := rv.MethodByName(method) // check mv 是否存在 if !mv.IsValid() { fmt.Printf("mv is zero value, method %s not found\n", method) return } // 调用 // nil 这里代表参数 mv.Call(in) }
这篇关于经过99次失败后, 我总结了几点 Golang 反射的经验(附源码)的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!