一、Golang的interface
- interface是方法的集合, 其方法不需要实现
- interface的更重要的作用在于多态实现
interface定义方法
1 | type 接口名称 interface { |
interface使用
- 接口的使用不仅仅针对结构体,自定义类型、变量等等都可以实现接口。
- 如果一个接口没有任何方法,我们称为空接口,由于空接口没有方法,所以任何类型都实现了空接口。
- 要实现一个接口,必须实现该接口里面的所有方法。
1 | package main |
interface嵌套
go语言中的接口可以嵌套,可以理解为继承,子接口拥有父接口的所有方法,并且想要使用该子接口的话,必须将父接口和子接口的所有方法都实现。
1 | type Skills interface { |
多态的概念
上面提到了,go语言中interface是实现多态的一种形式,所多态,就是一种事物的多种形态,就像python调用方法的时候,我们不需要关注传入参数的类型,我们只需要让传入的参数可以被方法使用就可以。
同一个interface,不同的类型实现,都可以进行调用,它们都按照统一接口进行操作。
在上面的示例中,我们增加一个Teacher结构体,同样实现接口进行说明:
1 | package main |
通过interface 判断类型&类型转换
由于接口是一般类型,当我们使用接口时候可能不知道它是那个类型实现的,基本数据类型我们有对应的方法进行类型转换,当然接口类型也有类型转换。
当然我们也可以用这个方式来进行类型的判断。
类型转换示例:
1 | var s int |
类型判断示例:
1 | package main |
类型判断示例:
1 | package main |
interface 和 reflect反射
Golang的变量包含 type 和value两部分
- type 包括 static type和concrete type. static type就类似python的不可变类型(如int、string),concrete type是runtime系统看见的类型
- 类型断言能否成功,取决于变量的concrete type,而不是static type.
Golang的静态类型和interface类型
- Golang的指定类型的变量的type是静态的(也就是指定int、string这些的变量,它的type是static type),在创建变量的时候就已经确定
- Golang的interface的type是concrete type。
- 在Golang的实现中,每个interface变量都有一个对应pair,pair中记录了实际变量的值和类型(value, type):
Golang的反射
- interface及其pair的存在,是Golang中实现反射的前提,理解了pair,就更容易理解反射。反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。
- value是实际变量值,type是实际变量的类型。一个interface{}类型的变量包含了2个指针,一个指针指向值的类型【对应concrete type】,另外一个指针指向实际的值【对应value】。
二、反射reflect
反射是程序执行时检查其所拥有的结构。尤其是类型的一种能力。这是元编程的一种形式。它同一时候也是造成混淆的重要来源。
每一个语言的反射模型都不同, python比较类似反射的例子就是类的 hasattr 方法, 用来检测类是否包含某个方法或者属性
go语言中的反射通过refect包实现,reflect包实现了运行时反射,允许程序操作任意类型的对象。
reflect.Type
Type:Type类型用来表示一个go类型。
不是所有go类型的Type值都能使用所有方法。请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,应先使用Kind方法获知类型的分类。调用该分类不支持的方法会导致运行时的panic。
获取Type对象的方法:
1 | func TypeOf(i interface{}) Type |
示例:
1 | package main |
reflect.Type的方法
通用方法:
1 | // 通用方法 |
示例:
1 | package main |
其他方法:
1 | // 数值 |
示例:
1 | package main |
reflect.Value
不是所有go类型值的Value表示都能使用所有方法。请参见每个方法的文档获取使用限制。在调用有分类限定的方法时,应先使用Kind方法获知该值的分类。调用该分类不支持的方法会导致运行时的panic。
Value为go值提供了反射接口,获取Value对象方法:
1 | func ValueOf(i interface{}) Value |
示例:
1 | str := "wd" |
reflect.Value的方法
reflect.Value.Kind():获取变量类别,返回常量
1 | package main |
用于获取值方法:
1 | func (v Value) Int() int64 // 获取int类型值,如果 v 值不是有符号整型,则 panic。 |
设置值方法:
1 | func (v Value) SetInt(x int64) //设置int类型的值 |
其他方法:
1 | ##########结构体相关: |
示例一:获取和设置普通类型的值
1 | package main |
示例二:简单结构体操作
1 | package main |
示例三:通过反射调用结构体中的方法,通过reflect.Value.Method(i int).Call()或者reflect.Value.MethodByName(name string).Call()实现
1 | package main |