反射(reflection)是指在运行时,动态获取程序结构信息(元信息)的一种能力,是静态类型语言都支持的一种特性,如Java, golang等。这里主要详细介绍golang reflection相关知识

公司主营业务:网站设计制作、成都网站制作、移动网站开发等业务。帮助企业客户真正实现互联网宣传,提高企业的竞争能力。创新互联是一支青春激扬、勤奋敬业、活力青春激扬、勤奋敬业、活力澎湃、和谐高效的团队。公司秉承以“开放、自由、严谨、自律”为核心的企业文化,感谢他们对我们的高要求,感谢他们从不同领域给我们带来的挑战,让我们激情的团队有机会用头脑与智慧不断的给客户带来惊喜。创新互联推出海陵免费做网站回馈大家。
类型与接口(Types and interfaces)
type MyInt int var i int var j MyInt
i 为int类型,j为MyInt类型。虽然i,j底层类型均为int,但它们属于不同类型,没有转换不能相互赋值。
接口类型 interface, 表示一系列方法集合,任意concrete (non-interface) value 只要实现了接口方法,便可赋值给interface
// Reader is the interface that wraps the basic Read method.
type Reader interface {
Read(p []byte) (n int, err error)
}
// Writer is the interface that wraps the basic Write method.
type Writer interface {
Write(p []byte) (n int, err error)
}
var r io.Reader
r = os.Stdin
r = bufio.NewReader(r)
r = new(bytes.Buffer)
// and so onr变量的静态类型为io.Reader,实际类型可能是File, Buffer类型
interface{} 特殊接口类型,没有任何方法,因此任何类型都可赋值给它The representation of an interface
var r io.Reader r = new(bytes.Buffer)
r变量的具体类型是io.Reader,实际类型是bytes.Buffer,那么在运行时,golang是如何实现的呢?
一个interface类型的变量存储了2个信息, 一个值,类型对
赋给变量的值(concrete value)
变量值的类型描述符(value's type descriptor)
var r io.Reader
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
return nil, err
}
r = tty接口类型r 的tty, *os.File)
当然r变量的value tty不仅仅实现了io.Reader接口中的Read方法,还实现了io.Writer中的Write方法,因此可以进行
类型断言(type assertion),试图将r 转换为io.Writer
var w io.Writer w = r.(io.Writer)
此时,接口变量w的tty, *os.File),也就是说r,w 底层value是一样的,可以通过不同的type来暴露不同的方法出来。
继续讨论
var empty interface{}
empty = w //此处不需要type assertion,因为任意类型都可以看作实现了empty interface的方法接口变量empty的tty, *os.File)
Reflection
1. Reflection goes from interface value to reflection object.(接口类型---> 反射类型(reflect.Value,reflect.Type))
反射,可以获取interface类型变量的具体信息(
golang 反射包为reflect
// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i interface{}) Value //获取pair中的value
// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type //获取pair中的concrete typeeg:
var r io.Reader r = os.Stdin //: rValue := reflect.ValueOf(r) rType := reflect.TypeOf(r) fmt.Println("value:", rValue) fmt.Println("type :", rType) 输出: value: &{0xc04205a000} //指针 type : *os.File var f float64 f = 1.234 fmt.Println("f value:",reflect.ValueOf(f)) fmt.Println("f type :",reflect.TypeOf(f)) 输出: f value: 1.234 f type : float64
2. Reflection goes from reflection object to interface value. 反射类型(reflect.Value,reflect.Type) --> 接口类型
type User struct {
Id int
Name string
Age int
}
func (u User) ReflectCallFunc() {
fmt.Println("reflect learn")
}
user := User{1, "test", 13}
var i interface{}
i = user
uValue := reflect.ValueOf(i)
uType := reflect.TypeOf(i)
fmt.Println("uValue: ",uValue)
fmt.Println(uValue.Interface()) //转换为interface类型,unpack uValue.Interface().(User)
fmt.Println(uValue.Type())
fmt.Println("uValue,string: ",uType.String())
fmt.Println("uType: ",uType.Name())
for i := 0; i < uType.NumField(); i++ { //获取field信息
field := uType.Field(i)
value := uValue.Field(i).Interface()
fmt.Printf("%s: %v = %v\n", field.Name, field.Type, value)
}
for i := 0; i < uType.NumMethod(); i++ {// 获取method信息
method := uType.Method(i)
fmt.Printf("method[%d] = %s \n",i,method.Name)
}
fmt.Println(uValue.Kind())
fmt.Println(uType.Kind())3. To modify a reflection object, the value must be settable. 通过反射修改变量
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("settability of v:", v.CanSet()) //print: settability of v: false
v.SetFloat(7.1) // Error: will panic.不可修改的原因:we pass a copy of x to reflect.ValueOf, so the interface value created as the argument to reflect.ValueOf is a copy of x, not x itself
解决办法,传递指针!!
var x float64 = 3.4
p := reflect.ValueOf(&x) // Note: take the address of x.
fmt.Println("type of p:", p.Type())
fmt.Println("settability of p:", p.CanSet())
print:
type of p: *float64
settability of p: false //why ? p不可set,p指向的内容可set,p指向的内容即*p,如何获得p指向的内容?reflect.Value 的Elem方法,可以获取value 指向的内容
v := p.Elem()
fmt.Println("settability of v:", v.CanSet())//settability of v: true
v.SetFloat(7.1)
fmt.Println(v.Interface()) //7.1
fmt.Println(x) //7.14. Structs 反射操作实例
type T struct {
A int
B string
}
t := T{23, "skidoo"}
s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Printf("%d:%v %s %s = %v\n", i, s.Kind(), typeOfT.Field(i).Name, f.Type(), f.Interface())
}
fmt.Println("canSet:",s.CanSet())
s.Field(0).SetInt(24)
s.Field(1).SetString("Sunset Strip")
fmt.Println("after change: ",s.Interface())5. 通过reflect 来调用方法
type User struct {
Id int
Name string
Age int
}
func (u User) ReflectCallFunc() {
fmt.Println("reflect learn")
}
func (u User) FuncHasArgs(name string, age int) {
fmt.Println("FuncHasArgs name: ", name, ", age:", age, "and origal User.Name:", u.Name)
}
func (u User) FuncNoArgs() {
fmt.Println("FuncNoArgs")
}
user := User{1, "test", 13}
uValue := reflect.ValueOf(user)
uType := reflect.TypeOf(user)
m1 := uValue.MethodByName("FuncHasArgs")
m2 := uValue.MethodByName("FuncNoArgs")
m ,b := uType.MethodByName("FuncNoArgs")
args := []reflect.Value{reflect.ValueOf("xiong"), reflect.ValueOf(30)}
m1.Call(args)
args = make([]reflect.Value,0)
m2.Call(args)
fmt.Println("m1:",m1)
fmt.Println("m2:",m2)
fmt.Printf("m:%#v,isfound:%v\n",m,b)
fmt.Println(m1)
当前题目:理解golang反射(reflectioninGo)
浏览路径:http://www.scyingshan.cn/article/pcidco.html


咨询
建站咨询
