总结
- 通过考虑数据类型之间的相同功能来创建抽象,而不是相同字段
- interface{} 的值不是任意类型,而是 interface{} 类型
- 接口包含两个字的大小,类似于 (type, value)
- 函数可以接受 interface{} 作为参数,但最好不要返回 interface{}
- 指针类型可以调用其所指向的值的方法,反过来不可以
- 函数中的参数甚至接受者都是通过值传递
- 一个接口的值就是就是接口而已,跟指针没什么关系
- 如果你想在方法中修改指针所指向的值,使用 * 操作符
Golang中的interface和interface{}
接口是一组方法签名(声明的是一组方法的集合)。当一个类型为接口中的所有方法提供定义时,它被称为实现该接口。
这是 Go 类型系统的核心概念:我们根据类型可以执行的操作而不是其所能容纳的数据类型来设计抽象。 —重点
interface{}类型
interface{} 类型,空接口,是导致很多混淆的根源。interface{} 类型是没有方法的接口。由于没有 implements 关键字,所以所有类型都至少实现了 0 个方法,所以 所有类型都实现了空接口。这意味着,如果您编写一个函数以 interface{} 值作为参数,那么您可以为该函数提供任何值。
// 新手们会认为 v 是任意类型的,但这是错误的。v 不是任意类型,它是 interface{} 类型。
// 对的,没错!当将值传递给DoSomething 函数时,
// Go 运行时将执行类型转换(如果需要),并将值转换为 interface{} 类型的值。
// 所有值在运行时只有一个类型,而 v 的一个静态类型是 interface{} 。
一个接口值由两个字(32 位机器一个字是 32 bits,64 位机器一个字是 64 bits)组成;一个字用于指向该值底层类型的方法表,另一个字用于指向实际数据。
// ifaceWords is interface{} internal representation.
type ifaceWords struct {
typ unsafe.Pointer
data unsafe.Pointer
}
指针和接口
接口的另一个微妙之处是接口定义没有规定一个实现者是否应该使用一个指针接收器或一个值接收器来实现接口。当给定一个接口值时,不能保证底层类型是否为指针。
一个指针类型可以通过其相关的值类型来访问值类型的方法,但是反过来不行。即,一个 *Dog 类型的值可以使用定义在 Dog 类型上的 Speak() 方法,而 Cat 类型的值不能访问定义在 *Cat 类型上的方法。