鸭子类型
- 通俗来讲,就是具有鸭子的特征他就是鸭子,比如鸭子用两条腿走路,鸡也是两条腿走路,那么在两条腿走路这个维度区分,那他就是鸭子
- 鸭子模型更加强调的是行为,而非内部结构
- 其他语言实现接口时使用的显式实现,即 显示使用implement 实现某些特殊,而go语言是隐式实现
接口定义 (无需使用implement显式实现)
注意: go接口如果定义指针接收者实现接口,那么实例化值进行调用时是无法调用的,反之则可以;即值接收者包含指针接收者,反之不包含
type Duck interface {
// 存放方法,即鸭子的行为
Run()
}
// 实现接口
type pskDuck struct {
}
func (p *pskDuck) Run() {
fmt.Println("可达鸭在跑")
}
func main() {
var d Duck = &pskDuck{}
d.Run()
}
结构体内嵌接口使用
- 使用场景: 使用了一个orm包,orm自带的有一套日志系统,但是你想使用自定的日志系统,那么只要你定义了一套实现了日志接口类,调用设置方法设置即可
func main() {
orm := NewOrm()
orm.Info("ORM 默认日志系统") // 使用orm默认
// 使用自定义日志系统
orm.SetLog(&CustomLog{})
orm.Info("这是自定义打印的")
}
type Orm struct {
LogWriter
}
func NewOrm() *Orm {
return &Orm{
&OrmDefaultLog{},
}
}
// 设置自定义日志处理器
func (o *Orm) SetLog(l LogWriter) {
o.LogWriter = l
}
// 日志处理器接口
type LogWriter interface {
Info(s string)
}
// Orm 默认日志处理器
type OrmDefaultLog struct {}
func (o *OrmDefaultLog) Info(s string) {
fmt.Println(fmt.Sprintf("Info日志:%v",s))
}
// 自定义日志处理器
type CustomLog struct {}
func (c *CustomLog) Info(s string) {
fmt.Println(fmt.Sprintf("自定义:%v",s))
}
空接口interface{}和断言
func add (a,b interface{}) interface{} {
switch a.(type) {
case int:
at,_:=a.(int)
bt,_:=b.(int)
return at+bt
case float64:
at,_:=a.(float64)
bt,_:=b.(float64)
return at+bt
default:
panic("类型不正确")
}
return 0
}
func main() {
a1 :=1
a2 :=2
re := add(a1,a2)
fmt.Println(re)
}
接口嵌套
- 接口可以通过嵌套达到更加灵活的效果
容器类型为interface{}类型时需要注意的点
- []interface{} 和 []string 类型是不通用的
func Info(arr []interface{}) {
for _, v := range arr{
fmt.Println(v)
}
}
func main() {
arr1 := []interface{}{
"我是",
"谁",
123,
}
Info(arr1) // 调用无问题
arr2 :=[]string{
"我是",
"谁",
}
Info(arr2) // 此处调用时会报错的,需要转为 []interface{} 类型才可以
}