写点什么

Go- 反射

用户头像
HelloBug
关注
发布于: 3 小时前
Go- 反射

Go 学习笔记,学习内容《Go入门指南》


主要介绍以下内容:

  • 方法和类型的反射

  • 通过反射修改值

  • 反射结构体


代码示例可以直接运行

package main
import ( "fmt" "reflect")
func printDivider(str ...string) { fmt.Println() fmt.Println("-----------------------------------------------") if len(str) > 0 { fmt.Println(str) }}
/* 假设我们知道一个变量secrect,但是不知道他是什么类型,如何使用,这里对其进行探索 */type NotKnownType struct { s1, s2, s3 string}
func (n NotKnownType) String() string { return n.s1 + "-" + n.s2 + "-" + n.s3}
/* 假设我们知道一个变量secrect,但是不知道他是什么类型,如何使用,这里对其进行探索 */var secrect interface{} = NotKnownType{"Ada", "Go", "Play"}
type UpperLowerCase struct { A int b string}
func main() { /* 方法和类型的反射 reflect.ValueOf、reflect.TypeOf 除非真的有必要,否则应当避免使用或小心使用该包 */ printDivider("方法和类型的反射") var f1 float32 = 5.6 fmt.Println(reflect.ValueOf(f1)) // 输出:5.6 fmt.Println(reflect.TypeOf(f1)) // 输出:float32 if reflect.TypeOf(f1).String() == "float32" { fmt.Println("Type of f1 is float32") // 输出:Type of f1 is float32 }
v1 := reflect.ValueOf(f1) fmt.Println(v1.Kind()) // 输出:float32 fmt.Println(v1.Type()) // 输出:float32 fmt.Println(v1.Float()) // 输出:5.599999904632568 获得f1变量的真实的值,同理可用Int()、Bool() fmt.Println(v1.Interface()) // 输出:5.6 fmt.Println(v1.Interface().(float32)) // 输出:5.6 if v1.Kind().String() == "float32" { fmt.Println("Return of Kind() must Convent to string") }
if v1.Type().String() == "float32" { fmt.Println("Return of Type() must Convent to string") }
/* 通过反射修改值 */ printDivider("通过反射修改值") var i1 int = 8 v2 := reflect.ValueOf(i1) // v2的类型: type reflect.Value fmt.Println(v2) // 输出:8 v2是i1的值拷贝 //v2 = 32 编译错误: cannot use 32 (type int) as type reflect.Value in assignment //v2.SetInt(32) // 运行时错误:panic: reflect: reflect.Value.SetInt using unaddressable value fmt.Printf("Can you set value of v2? %t\n", v2.CanSet()) // 输出:Can you set value of v2? false
v2 = reflect.ValueOf(&i1) fmt.Printf("Can you set value of v2? %t\n", v2.CanSet()) // 输出:Can you set value of v2? false fmt.Println(&i1) // 输出:0xc00000a138 fmt.Println(v2) // 输出:0xc00000a138 v2是一个地址 v2 = v2.Elem() fmt.Println(v2) // 输出:8 fmt.Printf("Can you set value of v2? %t\n", v2.CanSet()) // 输出:Can you set value of v2? true v2.SetInt(32) fmt.Printf("New value of v2 = %d\n", v2) // New value of v2 = 32 fmt.Printf("New value of i1 = %d\n", i1) // New value of i1 = 32
/* 反射结构体 */ printDivider("反射结构体") value := reflect.ValueOf(secrect) typ := reflect.TypeOf(secrect) fmt.Println("Value of secrect: ", value) // 输出:Value of secrect: Ada-Go-Play fmt.Println("Type of secrect: ", typ) // 输出:Type of secrect: main.NotKnownType
kin := value.Kind() fmt.Println("Kind of value secrect: ", kin) // 输出:Kind of value secrect: struct
for i := 0; i < value.NumField(); i++ { fmt.Printf("Field %d: %v\n", i, value.Field(i)) } /* 输出: Field 0: Ada Field 1: Go Field 2: Play */
results := value.Method(0).Call(nil) // 调用接口体上的第一个方法,即String方法 fmt.Println(results) //results = value.Method(1).Call(nil) // 输出:panic: reflect: Method index out of range
ul := UpperLowerCase{2, "Hello"} value = reflect.ValueOf(&ul).Elem() fmt.Println(value) // 输出:{2 Hello}
value.Field(0).SetInt(23) /* 结构体UpperLowerCase中的字段b是小写,属于未导出字段,不能使用 */ //value.Field(1).SetString("Go") // 运行错误:panic: reflect: reflect.Value.SetString using value obtained using unexported field fmt.Println(value) // 输出:{23 Hello}}
复制代码


发布于: 3 小时前阅读数: 4
用户头像

HelloBug

关注

还未添加个人签名 2018.09.20 加入

还未添加个人简介

评论

发布
暂无评论
Go- 反射