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. 痞子衡嵌入式:超级下载算法RT-UFL v1.0在Keil MDK下的使用

    痞子衡主导的"学术"项目 <RT-UFL - 一个适用全平台i.MXRT的超级下载算法设计> v1.0 版发布近 4 个月了,部分客户已经在实际项目开发调试中用上了这个 ...

  2. UltraSoft - Beta - Scrum Meeting 10

    Date: May 26th, 2020. Scrum 情况汇报 进度情况 组员 负责 今日进度 q2l PM.后端 记录Scrum Meeting Liuzh 前端 暂无 Kkkk 前端 前端增加了 ...

  3. [对对子队]会议记录4.17(Scrum Meeting8)

    今天已完成的工作 何瑞 ​ 工作内容:修复了一些bug,优化了UI ​ 相关issue:搭建关卡1 ​ 相关签入:4.17签入1 吴昭邦 ​ 工作内容:做了一些流水线系统的错误处理,添加了合成失败了之 ...

  4. [no code][scrum meeting] Alpha 13

    项目 内容 会议时间 2020-04-21 会议主题 OCR技术对接会议 会议时长 45min 参会人员 全体成员 $( "#cnblogs_post_body" ).catalo ...

  5. time_formatter攻防世界学习

    time_formatter 前言:这题说实话分析量蛮大的,首先是程序内壁比较绕,而且调用了之前许多没有见到的函数---如snprintf_che,以及strsup(好像打错了),getegid(), ...

  6. C++ Boost signal2信号/插槽

    #include "stdafx.h" #include "boost/signals2.hpp" #include "boost/bind.hpp& ...

  7. X264编码测试验证

    之前在做一个rtsp直播需求,其中一个方案是要用的x264来对摄像头数据进行实时编码推流,摄像头帧率是25fps,为了验证方案的可行性,先对x264的编码速度进行一个测试研究,再确认是否要采用此方案. ...

  8. JAVA笔记6__抽象类/接口/多态/instanceof关键字、父类设计法则

    /** * 抽象类:很多具有相同特征和行为的类可以抽象为一个抽象类 * 1.抽象类可以没有抽象方法,有抽象方法的类必须是抽象类 * 2.非抽象类继承抽象类必须实现抽象方法[可以是空实现] * 3.抽象 ...

  9. Arraylist,LinkedList和Vector的异同

    相同: 都是List接口的常用类,List接口:存储有序,可重复的数据 差异: ArrayList: 是作为List接口中的主要实现的类:线程不安全,效率高.底层使用是Object[] element ...

  10. 修改记事本PE结构弹计算器Shellcode

    目录 修改记事本PE结构弹计算器Shellcode 0x00 前言 0x01 添加新节 修改节数量 节表位置 添加新节表信息 0x02 添加弹计算器Shellcode 修改代码 0x03 修改入口点 ...