一、继承
可以通过在一个结构体中嵌入另一个结构体的方式,
假设我们有一个名为 Animal 的结构体:
type Animal struct {
name string
}
func (a *Animal) Move() {
fmt.Printf("%s is moving\n", a.name)
}
然后我们可以通过嵌入 Animal 结构体来定义一个新的结构体 Dog:
type Dog struct {
*Animal // 嵌入 Animal 结构体
}
func main() {
dog := &Dog{&Animal{"doggy"}}
dog.Move() // 调用 Animal 结构体中的 Move 方法
}
*Animal
全限定名
二、接口
2.1 接口定义
接口(interface)合约类型(contract type)
2.2 接口实现
一个类型如果拥有一个接口需要的所有方法,那么这个类型就实现了这个接口
假设我们定义一个Usb的接口,手机和电脑都可以插入,并提供了一个Start方法
type Usb interface {
Start()
}
现在我们提供了小米和苹果手机去插入
type Phone struct {
}
type Xiaomi struct {
}
//phone结构体实现Usb的方法
func (p Phone)Start(){
fmt.Println("我的苹果手机插入了!!!")
}
func (p Phone)Stop(){
fmt.Println("我的苹果手机拔出了!!!")
}
// xiaomi结构体实现Usb的方法
func (x Xiaomi)Start(){
fmt.Println("我的小米手机插入了!!!")
}
func (x Xiaomi)Start(){
fmt.Println("我的小米手机插入了!!!")
}
上述两个结构体实现了Usb的所有方法,那么我们就可以说该结构体已经实现了Usb接口,现在我们进行调用。
func (c Computer) Working(usb ...Usb) {
for _, u := range usb {
u.Start()
u.Stop()
}
}
我们这块使用了多态的思想(一个方法在不同的类型中具有不同的行为),定义一个方法Working去处理
c := Computer{}
p := Phone{}
x := Xiaomi{}
//多态的体现
c.Working(p,x)
2.3 接口注意事项
实现接口的类型必须实现接口中定义的所有方法。
三、类型断言
3.1 定义
将接口类型的值转换为其它类型的方法
3.2 类型断言的方式
- 基于接口的类型断言
x.(T)
var i interface{} = "hello"
s := i.(string) // 正确,s 的值为 "hello"
n := i.(int) // 错误,将导致运行时错误
需要注意的是,在使用基于接口值的类型断言时,需要确保接口值不为 nil,否则将引发运行时错误。因此,可以使用 if 语句结合类型断言来检查接口值的类型,例如:
var i interface{} = "hello"
if s, ok := i.(string); ok {
fmt.Println("i is a string:", s)
} else {
fmt.Println("i is not a string")
}