Go语言之初识接口

作者: 有财君 | 来源:发表于2019-05-10 23:38 被阅读578次
题图

1. 从Java说起接口

Java的接口是一种很好的东西,一定程度上解决了Java只允许单根继承的限制。我们可以认为接口是一种约定,它规定了一个类应该具有什么样的能力。

很久以来,只要掌握了接口,写代码都会变得很容易,这就叫做“面向接口编程”。

我个人就很喜欢用接口。

比如我们学习Java的时候,很多入门教材上都会举汽车作为继承的例子,汽车作为父类,下面会有小汽车,公交车,跑车或者越野车种种子类。那么这个时候我就可以实现一个汽车的接口:

public interface Car {
    void run();
}

之后所有的子类都可以实现这个接口,比如公交车:

public class Bus implement Car {
    @Override
    public void run() {
    ...
    }
}

接口最大的作用之一就是实现多态,这是面向对象的一大特性:

Car bus = new Bus();

多态就这么自然而然的实现了。

2. Go的接口

接口为了实现多态,这一点其实在Go上也不例外。先上一段代码,准备说明问题:

package main

import "fmt"

//接口倒是很像Java,声明了方法
type notifier interface {
    notify()
}

//定义普通用户
type user struct {
    name string
    email string
}

//定义管理员用户,还有个权限域
type admin struct {
    name string
    email string
    privilege string
}

func (u *user) notify() {
    fmt.Println("name:", u.name, "send mail to: ", u.email)
}

func (a *admin) notify() {
    fmt.Println("name: ", a.name, "send mail to: ", a.email, "has privileges: ", a.privilege)
}

func sendNotify(n notifier) {
    n.notify()
}

func main() {
    u := user{"lee", "lee@126.com"}
    a := admin{"zhang", "zhang@126.com", "delete"}
    sendNotify(&u)
    sendNotify(&a)
}

下面说明一下:

  • 首先我声明了一个接口notifier,接口有一个notify的方法;

  • 接下来我利用结构体定义两个类型user和admin;

  • 接下来我声明了两个notify方法,不过就是接收者不同;

  • 到此时只是实现了notify方法,但是还是看不出多态在哪里体现,下面先看看main函数;

  • u和a分别是user和admin类型,但是他们都能作为参数传给sendNotify函数;

  • sendNotify函数的入参是notifier接口类型。

到这里,我们大致可以理解为user和admin都实现了notifier接口,只是实现的方式和Java是有天壤之别的。

这里有个地方要特别注意一下,我在实现接口的时候,接收者定义了指针类型,那么只有指向这个类型(notifier)的指针才能实现对应的接口,因此sendNotify函数接收的参数一定是指针。

但是如果实现的时候改成这样:

func (u user) notify() {
    fmt.Println("name:", u.name, "send mail to: ", u.email)
}

func (a admin) notify() {
    fmt.Println("name: ", a.name, "send mail to: ", a.email, "has privileges: ", a.privilege)
}

就可以直接传值的方式了:

func main() {
    u := user{"lee", "lee@126.com"}
    a := admin{"zhang", "zhang@126.com", "delete"}
    sendNotify(u)
    sendNotify(a)
}

这就牵扯到方法集规则的问题了,方法集规则如下定义:

Values Method Receivers
T (t T)
*T (t T)and(t *T)

这就能解释这种代码为什么对:

func (u *user) notify() {
    fmt.Println("name:", u.name, "send mail to: ", u.email)
}

func (a *admin) notify() {
    fmt.Println("name: ", a.name, "send mail to: ", a.email, "has privileges: ", a.privilege)
}

func main() {
    u := user{"lee", "lee@126.com"}
    a := admin{"zhang", "zhang@126.com", "delete"}
    //虽然方法的接收者定义为指针,但是直接传值也无所谓,这是方法集规则
    u.notify()
    a.notify()
}

但是,从接收者的角度来看,就变成了这样:

Method Receivers Value
(t T) T and *T
(t *T) *T

这样,用指针作为接收者实现的接口,能接收的只能指针了。

3. 小结

其实接口只是Go语言的类型系统中的一种,不过可以借助接口实现多态,这是很不错的一种方式,虽然和Java差别有点大。

不过已经掌握了一门编程语言的人,在遇到了一个喜欢的语言的时候,想学习就会很快了。

参考:《Go IN ACTION》

喜欢或者帮助到了你,点个赞吧。

相关文章

  • golang的helloworld

    go语言初识 go语言的变量

  • go语言基础

    go语言基础 go 语言接口

  • 第11章 1.接口定义

    1、初识接口 2、 直接定义接口实例 3、 判断类型,相当于typeof 4、方法集调用规则 Go 语言规范定义了...

  • 初识Go语言-1

    Go语言学习路径 初识Go语言 Go语言环境搭建与IDE安装 Go语言基础语法 Go语言数据类型 Go语言变量和常...

  • Go语言之初识接口

    1. 从Java说起接口 Java的接口是一种很好的东西,一定程度上解决了Java只允许单根继承的限制。我们可以认...

  • GO语言——入门(1)

    一、初识GO语言 1.GO语言介绍 1.1 GO语言是什么 2009年11月10日,GO语言正式成为开源编程语言家...

  • 初识go语言

    title: 初识go语言tag: golang 编程语言categories: notes 简介 Go语言是一门...

  • 以太坊私有链搭建+挖矿+转账

    初识以太坊 以太坊介绍链接 以太坊官方 选择语言 选择以GO语言开发的Go-ethereum项目 GO语言安装 安...

  • 课程目录

    初识Go语言 Go语言的特性 环境搭建 分享人:洪波 时间:2019-6-25 17:00-18:00 Go语...

  • 初识Go语言

    Go 语言结构 初识Go语言 Go 语言结构 代码说明: ① 定义包名,必须在源文件中非注释的第一行指明这个文件...

网友评论

    本文标题:Go语言之初识接口

    本文链接:https://www.haomeiwen.com/subject/qpgzoqtx.html