09-interface接口
发布于 2026-08-20
09-interface接口
1、鸭子类型
go语言中处处都是interface,到处都是鸭子类型(duck typing)。
Go 不关心你是什么类型,只关心你有没有实现我需要的方法。“走起来像鸭子,叫起来像鸭子,那它就是鸭子”
拿js举例:
假设有一个函数:
javascript
function makeSound(animal) {
animal.sound();
}这个函数根本不关心 animal 是什么,只要有 sound() 方法就行。
javascript
const dog = {
sound() {
console.log("wang");
},
};
const cat = {
sound() {
console.log("miao");
},
};
makeSound(dog);
makeSound(cat);这里:dog 不是 Animal、cat 不是 Animal、但是都有sound,所以都能传进去,这就是 JS 的鸭子类型。
go中鸭子类型强调的是事物的外部行为,而不是内部结构
2、接口的定义和实现
go
package main
import "fmt"
_// __接口的定义__,定义需要实现的方法_
type Duck interface {
Gaga()
Walk()
}
_// 接口的实现,需要定义一个struct,然后去绑定方法_
type myDuck struct {
name string
}
_// 实现Duck的方法,这样我的myDuck结构体就实现了Duck接口的方法,在使用的时候,就可以直接使用Duck了_
func (md myDuck) Gaga() {
fmt.Println("duck Gaga")
}
func (md myDuck) Walk() {
fmt.Println("duck Walk")
}
func main() {
_// 这个就类似 myDuck implements Duck_
_ _var duck Duck = myDuck{}
duck.Walk()
}如果我的interface为空,就代表可以实现任何方法,其实就是go中any类型的实现
go
type Duck interface {}any类型
interface{}和any是等价的

3、多接口的实现
go
package main
import "fmt"
// ***************************************************************
type FileWriter struct {
filePath string
}
_// 实现一个文件写入方法_
func (fw *FileWriter) Writer(filename string) error {
fw.filePath = filename
fmt.Println("writer file path:", fw.filePath)
return nil
}
// ***************************************************************
type DatabaseWriter struct {
sql string
}
_// 实现一个数据库写入方法_
func (dw *DatabaseWriter) Writer(sql string) error {
dw.db = sql
fmt.Println("writer db sql:", sql)
return nil
}
// ***************************************************************
// 定义一个写的接口
type WriterInterface interface {
Writer(string) error
}
// 我的结构体中使用interface类型
type MyWriter struct {
WriterInterface
}
func main() {
var mw_file WriterInterface = MyWriter{
&FileWriter{"./demo.txt"},
}
var mw_db WriterInterface = MyWriter{
&DatabaseWriter{"sql"},
}
}在结构体中包含interface,需要在外部使用已经实现好的接口方法,可以做到解耦
4、类型断言
通过interface解决动态类型传参,也就是需要用到类型断言
语法:v := i.(T),第二个参数会返回一个bool,用于判断转换抛出的错误
举例:
5、接口嵌套
接口嵌套就是在接口中可以引入接口,实现类似继承的效果
注意:下面有两种写法
- 如果具体的方法实现,采用的是指针(S *SReadWriter),那么使用这个实现的方法的结构体时候,就必须携带取地址(&SReadWriter{})
- 如果具体的方法不是采用指针,采用的是值对象方式(S SReadWriter),那么就可以携带也可以不用携带取地址(&SReadWriter{}或SReadWriter{})
6、error类型

error类型底层也是interface,只要是实现了Error方法的结构体,就是error