golang知识点--reflect

相关知识学习

1.go语言的type和interface{}

类型
go语言是静态类型的语言,这意味着每个变量都有它的静态类型,那是确定且一直固定的一个类型。
例如:

type MyInt int

var i int
var j MyInt

虽然定义了MyInt是int的别名,但是i与j的类型并不是一个类型,除非经过转换。
接口概述
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)
}

任何使用此签名实现了Read(Write)的类型,都可以说实现了io.Reader(io.Writer),举一个例子说明io.Reader类型的变量可以保存期类型具有Read方法的任何值:

type test struct{
  a int
}
func (f *test) Read(p []byte) (n int, err error) {
	return 0,nil
}

func main() {
	var b *test
	var r io.Reader
	r = b
}

要记得无论r的具体值是多少r的类型都是io.Reader
一个及其重要的接口类型是空interface

interface{}

它表示方法的空集合,并且完全由任何值满足,因为任何值都有零个或多个方法。要明确接口都是静态类型的,无论他们存储的值如何他们的类型都不变。

var b *test
	var a int
	var r interface{}
	r = b
	fmt.Println(reflect.TypeOf(r))//*main.test
	r = a
	fmt.Println(reflect.TypeOf(r))//int

接口详解
一个接口类型的变量存储一对数据:
(1)指定给变量的具体值(实现接口的底层具体数据项)
(2)该值的类型描述符(描述该项的完整类型)

var r io.Reader
tty, err := os.OpenFile("/dev/tty", os.O_RDWR, 0)
if err != nil {
    return nil, err
}
r = tty

r表示如下:(value,type)对(tty,*os.File)

2.反射定律

1.反射从接口值到反射对象。

func TypeOf(i interface{}) Type {
	eface := *(*emptyInterface)(unsafe.Pointer(&i))
	return toType(eface.typ)
}

当我们调用typeof的时候实际上我们是先将x作为一个空interface传递,
然后typeof解压空interface来回复类型信息。

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())

输出

type: float64
kind is float64: true
value: 3.4

2.反射从反射对象到接口值。
与物理反射一样,Go中的反射也会产生自身的逆反射

y := v.Interface().(float64) // y will have type float64.
fmt.Println(y)

3.若要修改反射对象,该值必须是可设置的
错误示范:

var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.

会发现v的值是不可以被设置的。可设置性是反射值的一个属性,并非所有反射值都具有它。
如何查看这个值是否可设置

var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("settability of v:", v.CanSet())

可设置性:可设置性有点像可寻址性,但更严格。反射对象可以修改用于创建反射对象的实际存储的属性。可设置性由反射对象是否保存原始项决定。
若要通过反射修改x,必须给反射库一个指向要修改的值得指针。

	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())
	v := p.Elem()
	fmt.Println("settability of v:", v.CanSet())
	v.SetFloat(7.1)
	fmt.Println(v.Interface())
	fmt.Println(x)

输出:

type of p: *float64
settability of p: false
settability of v: true
7.1
7.1

参考页面:
https://blog.golang.org/laws-of-reflection

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值