go定义接口以及类怎么使用接口

多态是指代码可以根据类型的具体实现采取不同行为的能力。如果一个类型实现了某个接口,所有使用这个接口的地方,都可以支持这种类型的值。

  • 接口是用来定义行为的类型。这些被定义的行为不由接口直接实现,而是通过方法由用户定义的类型实现。如果用户定义的类型实现了某个接口类型声明的一组方法,那么这个用户定义的类型的值就可以赋给这个接口类型的值。这个赋值会把用户定义的类型的值存入接口类型的值。对接口值方法的调用会执行接口值里存储的用户定义的类型的值对应的方法。因为任何用户定义的类型都可以实现任何接口,所以对接口值方法的调用自然就是一种多态。

下面将创建一个用户定义结构体并实现一个发送接口:

package main

import "fmt"

// 定义一个notifier接口
// 通知类行为的一个接口
type notifier interface {
notify()
} // 定义一个用户类
type user struct {
name string
email string
} // nofity是使用指针接收者实现的方法
func (u *user) notify() {
fmt.Print("发送一条邮件给%s<%s>", u.name, u.email)
} func main() {
// 创建一个用户并复制
user := user{"小明", "1001**@qq.com"}
sendNotification(&user)
} func sendNotification(n notifier) {
n.notify()
}

注意:这里传递给sendNotification方法的用户定义结构体值user,是使用引用的方式传递的。因为类在实现接口的时候传递的参数是引用类型:(u *user),如果你是使用值传递的话,编辑器会报错。

./demo.go:25:18: cannot use user (type user) as type notifier in argument to sendNotification:
user does not implement notifier (notify method has pointer receiver)

进一步探索新问题,为什么上述使用值不行,使用引用可以呢?

如果你把是实现接口的传递参数改成值的形式而不是引用,你将会发现有所不同

// nofity是使用指针接收者实现的方法
func (u user) notify() {
fmt.Print("发送一条邮件给%s<%s>", u.name, u.email)
}

// 创建一个用户并复制
user := user{"小明", "1001**@qq.com"}
sendNotification(user)
sendNotification(&user)

你将会发现,使用引用的方式调用跟使用值的方式调用,编译器都不会报错,这是为什么?

  • 因为底层实现是如果使用指针来实现一个接口(u *user),那么只有指向那个类型(user)的指针才能实现对应的接口。
  • 如果使用值来实现一个接口,那么那个类型(user)的值和指针都能够实现对应的接口。

注意:使用指针实现接口和使用值实现接口有个区别在于,指针是指向内存同一块地址的,所以通过指针传递的参数,在函数体内执行结构体的改变会影响函数外的用户类型值,而使用值传递则不会 ,这也是在使用指针和使用值的不同场景选择的一个区别其中之一。

使用值:

package main

import "fmt"

// 定义一个notifier接口
// 通知类行为的一个接口
type notifier interface {
notify()
} // 定义一个用户类
type user struct {
name string
email string
} // nofity是使用指针接收者实现的方法
func (u user) notify() {
u.name = "小红"
fmt.Print("发送一条邮件给%s<%s>", u.name, u.email)
} func main() {
// 创建一个用户并复制
user := user{"小明", "1001**@qq.com"}
//sendNotification(user)
sendNotification(&user) // 小明
fmt.Println(user.name)
sendNotification(user) // 小明
fmt.Println(user.name) } func sendNotification(n notifier) {
n.notify()
}

使用指针:

package main

import "fmt"

// 定义一个notifier接口
// 通知类行为的一个接口
type notifier interface {
notify()
} // 定义一个用户类
type user struct {
name string
email string
} // nofity是使用指针接收者实现的方法
func (u *user) notify() {
u.name = "小红"
fmt.Print("发送一条邮件给%s<%s>", u.name, u.email)
} func main() {
// 创建一个用户并复制
user := user{"小明", "1001**@qq.com"}
//sendNotification(user)
sendNotification(&user) // 小红
fmt.Println(user.name) } func sendNotification(n notifier) {
n.notify()
}

go定义接口以及类怎么使用接口的更多相关文章

  1. Java基础之Comparable接口, Collections类,Iterator接口,泛型(Generic)

    一.Comparable接口, Collections类 List的常用算法: sort(List); 排序,如果需要对自定义的类进行排序, 那就必须要让其实现Comparable接口, 实现比较两个 ...

  2. Java 私有接口 【类中嵌套接口】

    1.前言 接口十分常用,能规范实现类的命名 和 实现多个实现类的向上转型成统一类型 ,但是接口的修饰符只能是 public吗? 当然不是,可以是private , 难道是像这样? 显然不可以,已经报错 ...

  3. PHP类继承、接口继承关系概述

    PHP类继承: PHP类不支持多继承,也就是子类只能继承一个父类,但是支持多层次继承,比如: class frist{ public function __construct(){ echo &quo ...

  4. Eclipse如何查看接口实现类快捷键

    1.找到要打开的接口类 2.双击接口名选中 3.按Ctrl+T打开接口实现类 以List接口为例,如下所示

  5. python接口自动化(五)--接口测试用例和接口测试报告模板(详解)

    简介 当今社会在测试领域,接口测试已经越来越多的被提及,被重视,而且现在好多招聘信息要对接口测试提出要求.区别于传统意义上的系统级别测试,很多测试人员在接触到接口测试的时候,也许对测试执行还可以比较顺 ...

  6. C#的接口基础教程之四 访问接口

    对接口成员的访问 对接口方法的调用和采用索引指示器访问的规则与类中的情况也是相同的.如果底层成员的命名与继承而来的高层成员一致,那么底层成员将覆盖同名的高层成员.但由于接口支持多继承,在多继承中,如果 ...

  7. 调试接口,返回的json数据,我定义了一个类,用来序列化,其中有一个字段定义为string 然后序列化的时候报错

    调试接口,返回的json数据,我定义了一个类,用来序列化,其中有一个字段定义为string 然后序列化的时候报错 在需要解析的类型类上加上声明 eg:

  8. Spring只定义接口自动代理接口实现类

    能够扫描到包 @ComponentScan("org.zxp.esclientrhl") ESCRegistrar类主要实现ImportBeanDefinitionRegistra ...

  9. python定义接口继承类

    zxq547 python定义接口继承类invalid syntax解决办法 1 2 3 4 5 6 7 class s_all(metaclass=abc.ABCMeta):     #python ...

随机推荐

  1. airtext初始化(一)

  2. JVM:Java中的引用

    JVM:Java中的引用 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 在原来的时候,我们谈到一个类的实例化 Person p = new Person() 在 ...

  3. 2021.8.13考试总结[NOIP模拟38]

    T1 a 入阵曲.枚举矩形上下界,之后从左到右扫一遍.用树状数组维护前缀和加特判可以$A$,更保险要脸的做法是双指针扫,因为前缀和单调不减. $code:$ 1 #include<bits/st ...

  4. Exynos4412 中断处理流程详解

    Linux 中,当外设触发中断后,大体处理流程如下: a -- 具体CPU architecture相关的模块会进行现场保护,然后调用machine driver对应的中断处理handler; b - ...

  5. series和读取外部数据

    1.为什么学习pandas 我们并不是不愿意学习新的知识,只是在学习之前我们更想知道学习他们能够帮助我们解决什么问题.--伟哥 numpy虽然能够帮助我们处理数值,但是pandas除了处理数值之外(基 ...

  6. 如何系统学习C 语言(上)之 基础篇

    大话C 语言(一) 初识C 语言 老实说,上大学之前我根本不知道什么是C 语言,所以当初学校开设这门课时,我是充满了好奇,所以当初我翻阅了大量的C 语言入门书籍,千篇一律,都是从一些概念.术语和理论讲 ...

  7. Win10下C语言转8086汇编

    目录 Win10下C语言转8086汇编 简介 开始 写C代码 转换成汇编代码 Win10下C语言转8086汇编 简介 最近学习<王爽汇编>,然后突发奇想,想一边写C语言用编译器将其翻译成汇 ...

  8. S 锁与 X 锁的爱恨情仇《死磕MySQL系列 四》

    系列文章 一.原来一条select语句在MySQL是这样执行的<死磕MySQL系列 一> 二.一生挚友redo log.binlog<死磕MySQL系列 二> 三.MySQL强 ...

  9. shell 中的判断

    一.if的基本语法: if [ command ];then    符合该条件执行的语句 elif [ command ];then    符合该条件执行的语句 else    符合该条件执行的语句 ...

  10. Redis INFO CPU 信息详解

    一.INFO CPU 通过INFO CPU命令可以查看Redis进程对于CPU的使用情况,如下: 这几个字段的含义如下所示: used_cpu_sys: System CPU consumed by ...