面试题答案
一键面试- 命名类型
Dog
实现Animal
接口:type Animal interface { Speak() } type Dog struct{} func (d Dog) Speak() { // 具体实现 }
- 未命名类型的结构体实现
Animal
接口:type Animal interface { Speak() } var a Animal = struct { name string }{ name: "无名狗", } func (s struct{name string}) Speak() { // 具体实现 }
- 不同表现及原因:
- 类型断言:
- 对于命名类型
Dog
,类型断言v, ok := a.(Dog)
可以准确判断接口a
是否持有Dog
类型的值,因为Dog
是明确的命名类型。原因是Go语言的类型系统对命名类型有明确的标识,在编译和运行时可以清晰地进行类型匹配。 - 对于未命名类型的结构体,不能使用
v, ok := a.(struct{name string})
这样的类型断言,因为未命名类型每次定义都是全新的类型,即使结构相同。在Go语言中,未命名类型主要用于匿名结构体字面量等场景,其类型的唯一性使得这样的断言无法实现。若要断言,可以先将其赋值给一个有命名的类型,再进行断言。
- 对于命名类型
- 接口赋值:
- 命名类型
Dog
只要实现了Animal
接口的方法,就可以赋值给Animal
接口类型的变量,如var a Animal = Dog{}
。这是因为Go语言的接口实现是隐式的,只要类型实现了接口的方法集,就可以赋值给该接口类型。 - 未命名类型的结构体同样只要实现了
Animal
接口的方法,也能赋值给Animal
接口类型的变量,如var a Animal = struct{name string}{}
。但由于其未命名,在不同地方定义的相同结构的未命名结构体是不同类型,而命名类型在整个程序中具有唯一性,这使得命名类型在接口赋值方面更具可复用性和可维护性。
- 命名类型
- 类型断言: