浅谈 interface{}
学了一段时间,对Go的认知还差很多,其中一个是困扰了我许久的一种类型
interface{}
,以下就谈谈对这个东西的理解。
引用一段话写的很好:原文地址
interface是一组method的集合,是duck-type programming的一种体现。接口做的事情就像是定义一个协议(规则),只要一台机器有洗衣服和甩干的功能,我就称它为洗衣机。不关心属性(数据),只关心行为(方法)。
假如我有两台电脑,一台华硕台式,一台华为轻薄本。这时候我想使用两台电脑打字,可以这样写:
package main
import (
"fmt"
)
// ASUS 华硕台式机
type ASUS struct {
Name string
KeyBord string
Mouse string
}
func (a *ASUS) Type() {
a.Name = "华硕"
fmt.Printf("正在使用<%s>电脑打字\n", a.Name)
}
// Huawei 华为轻薄本
type Huawei struct {
Name string
KeyBord string
Mouse string
}
func (h Huawei) Type() {
h.Name = "华为"
fmt.Printf("正在使用<%s>电脑打字\n", h.Name)
}
func main() {
var asus ASUS
asus.Type() // 正在使用<华硕>电脑打字
var huawei Huawei
huawei.Type() // 正在使用<华为>电脑打字
}
但是这样就会有一个问题就是,如果我公司有一百多太不同类型的电脑,我想让这些电脑都要有打字方法并且随时能够调用,这时该怎么办?是不是都要在main
函数中初始化每一个电脑的结构体再调用对应的Type()
方法?虽然这种方法可行,但是在编程上是不被赞同的,这样导致main
函数中的代码多而重复,代码高耦合做了很多无用功,还会导致代码难维护。最佳的解决方法就是引入interface{}
这个概念,这也是一种类型;可以这样做:
// Computer 电脑接口
type Computer interface {
Type()
}
func NewComputer(c Computer) Computer {
return c
}
func main() {
var asus ASUS
computer := NewComputer(&asus)
computer.Type() // 正在使用<华硕>电脑打字
}
添加一个Computer
接口,然后在main
中先初始化ASUS
电脑,然后在把asus
给到接口,然后接口知道当前接口知道要哪台电脑做打字操作。同理,如果想让华为电脑打字,就将传入接口中的结构体换成华为的就可以。
func main() {
//var asus ASUS
var huawei Huawei
computer := NewComputer(&huawei)
computer.Type() // 正在使用<华为>电脑打字
}
理解概念很重要,这里简单讲讲我对interface{}
,struct{}
,method
的认识:
- interface{} –> 广义一类东西,如:鸟,飞机,电脑,节日…
- struct{} –> 对广义的一类东西细分,然后附上其属性也就是字段,如:
- 鸟(麻雀<小>,鹦鹉<多彩>)
- 飞机(F35<机动性>,波音747<装载性>)
- 电脑(华硕电脑<体积大>,华为轻薄本<小而便捷>)
- 四大节日(春节<汤圆,饺子,年糕…>,清明<拜祖>,端午<粽子>,中秋<月饼>)
- meth –> 也就是方法,对这个的理解归于三个字:做什么,如:
- 鸟
- 麻雀(偷食)
- 鹦鹉(模仿)
- 飞机
- F35(载弹)
- 波音747(载客)
- 电脑
- 华硕(大型开发)
- 华为轻薄本(日常办公)
- 四大节日(PS:不会有人四大节日都忘了吧。)
- 春节(团圆)
- 清明(祭祀)
- 端午(平安)
- 中秋(思乡)
- 鸟
通过这种方法写一个节日组合
package main
import "fmt"
type Festival interface {
ToDo()
}
func NewFestival(f Festival) Festival {
return f
}
type Spring struct {
}
func (s *Spring) ToDo() {
fmt.Println("团圆")
}
type TombSweeping struct {
}
func (s *TombSweeping) ToDo() {
fmt.Println("祭祀")
}
type DragonBoat struct {
}
func (d *DragonBoat) ToDo() {
fmt.Println("祈福")
}
type MidAutumn struct {
}
func (m *MidAutumn) ToDo() {
fmt.Println("思乡")
}
func main() {
var db DragonBoat
festival := NewFestival(&db)
festival.ToDo() // 祈福
}
一个人走得很长,两个人会更有趣
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: