浅谈 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 协议》,转载必须注明作者和本文链接
讨论数量: 1

面向接口编程

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!
未填写
文章
1
粉丝
1
喜欢
0
收藏
0
排名:3017
访问:177
私信
所有博文
社区赞助商