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 加入
还未添加个人简介











 
    
评论