Go- 反射
发布于: 3 小时前
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
版权声明: 本文为 InfoQ 作者【HelloBug】的原创文章。
原文链接:【http://xie.infoq.cn/article/d2f398d3ba36553716b9b0ff9】。
本文遵守【CC BY-NC-ND】协议,转载请保留原文出处及本版权声明。
HelloBug
关注
还未添加个人签名 2018.09.20 加入
还未添加个人简介
评论