接口

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 官方关于反射的博客,反射有三大定律:

  1. Reflection goes from interface value to reflection object.
  2. Reflection goes from reflection object to interface value.
  3. 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 递归的打印