接口
Duck type
动态语言执行时检测,静态语言编译时检测(指定类型,更安全)。
Go编译时检测类型有没有实现接口的相关方法。
对象和对象指针接收器
- 在调用方法的时候,值类型既可以调用值接收者的方法,也可以调用指针接收者的方法;指针类型既可以调用指针接收者的方法,也可以调用值接收者的方法。(编译器自动转义)
- 如果方法的接收者是值类型,无论调用者是对象还是对象指针,修改的都是对象的副本,不影响调用者,所以接收者是值类型,会自动生成接受者为指针类型的方法;如果方法的接收者是指针类型,则调用者修改的是指针指向的对象本身。
不可以declare两遍!
iface eface
ifacetab一个 itabdata
itab_typeinterfun
interfacetype_type_typemhdrpkgpath
eface_typedata
接口的动态类型和动态值
tabdata
输出为:
只有当接口的动态类型和动态值都为nil的时候,接口才==nil。
编译器自动检测类型是否实现接口
检验 *myWriter是否实现了io.Writer接口
检验myWriter是否实现了io.Writer接口
类型断言(针对接口的类型转换)
fmt.PrintlninterfaceString()String()
接口转换的原理
mnO(mn)O(m+n)
1.具体类型转空接口时,_type 字段直接复制源类型的 _type;调用 mallocgc 获得一块新内存,把值复制进去,data 再指向这块新内存。
2.具体类型转非空接口时,入参 tab 是编译器在编译阶段预先生成好(编译阶段就知道类型是怎么转换的,__type 和 接口的类型都完全已知)的,新接口 tab 字段直接指向入参 tab 指向的 itab;调用 mallocgc 获得一块新内存,把值复制进去,data 再指向这块新内存。
3.而对于接口转接口(运行时处理,因为编译的时候itab的*__type还不知道,实体类型并不确定),itab 调用 getitab 函数获取。只用生成一次,之后直接从 hash 表中获取。
反射
基本概念
Go 语言提供了一种机制在运行时更新变量和检查它们的值、调用它们的方法,但是在编译时并不知道这些变量的具体类型,这称为反射机制。
基础的两个接口
Type的方法(获取__type的信息)
Value也有相关方法(反应了__type和data的信息)
反射的定律
根据 Go 官方关于反射的博客,反射有三大定律:
- Reflection goes from interface value to reflection object.
- Reflection goes from reflection object to interface value.
- To modify a reflection object, the value must be settable.
1和2是相互转换
3 要修改原变量,反射对象必须能代表原变量!
输出:
p.Elem()
注:
reflect.Elem()返回接口v包含的值或指针v指向的值。 如果v的Kind不是Interface或Ptr,会panic。如果v为零,它将返回零值。
reflect.Indirect()函数用于获取v指向的值,即如果v是nil指针,则Indirect返回零值,如果v不是指针,则Indirect返回v
用处
- Json的解析
- ORM
- fmt 递归的打印