在b站看到各食品讲解go的interface,引发我的兴趣007-go语言中的interface(上)原理
其中给出了一个模型来解释go的interface在内存上的形状,这样也许能更好理解一些
1 2 3 4 5 6 7 8 9
| package main
import "fmt" import "unsafe"
type interface_struct struct { Type unsafe.Pointer Data unsafe.Pointer }
|
特性理解
go的interface有点像cpp的抽象类里面的虚函数,但是又由于go本身的特性,导致其和cpp还是有一些区别
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| package main
import "fmt"
type Speaker interface { Speak() string }
type Dog struct {} type Person struct {}
func (d Dog) Speak() string { return "汪汪!" }
func (p Person) Speak() string { return "你好!" }
func MakeSound(s Speaker) { fmt.Println(s.Speak()) }
func main() { var s0 Speaker = &Person{} var s1 Speaker = (*Person)(nil) var s2 Speaker = nil
fmt.Println(s0 == nil) fmt.Println(s0.Speak())
fmt.Println(s1 == nil) fmt.Println(s1.Speak())
fmt.Println(s2 == nil) }
|
示例的结果类似于
1 2 3 4 5 6 7 8 9 10
| false 你好! false panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4982df]
goroutine 1 [running]: main.main() /home/dbgbgtf/Main/work/test_go/main.go:33 +0xbf exit status 2
|
可以看到s0和s1都被认为不是nil。但是在调用方法时,s0可以,s1却失败了
这里可以用cpp的理解来说,s0和s1都是Person类型的指针,但是由于s1是空指针,无法真正调用Speaker()
s1和s2的区别则在于类型,可以看到这里和cpp不一样。在赋值时,*Person的这个类型就应该被赋给s1了
所以在检查s1 == nil时,会返回一个false。因为s1的类型为*Person
而s2则是一个空类型空指针,所以在检查s2 == nil时,返回了true
实际使用?
我刚刚开始学go,还没写过什么go项目,所以只是猜测下
这个东西应该类似于cpp的抽象类,只不过他不能带上变量,而只能储存方法
可以比较好的抽象一些类似的结构体方法于一个类型