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. MySQL:提高笔记-4

    MySQL:提高笔记-4 学完基础的语法后,进一步对 MySQL 进行学习,前几篇为: MySQL:提高笔记-1 MySQL:提高笔记-2 MySQL:提高笔记-3 MySQL:提高笔记-4,本文 说 ...

  2. IDEA注释设置:从当前鼠标位置开始注释快捷键

    在写xml或html注释时,经常出现注释出来的时候都是顶格的,前面包含一大段空格,并没有在鼠标位置开始. 可在设置中进行修改,其他代码格式修改方法类似

  3. 方阵里面的dp

    打了一场luogu的信心赛,惊讶地发现我不会T2,感觉像这样在矩阵里面的dp看起来很套路的样子,但是仔细想想还是有很多需要注意的细节. 又想到之前貌似也考过一些类似的题目 然而我并没有改 ,于是打算补 ...

  4. 2021.5.24考试总结 [NOIP模拟3]

    带着爆0的心态考的试,没想到整了个假rk2 (炸鱼大佬wtz忒强了OTZ T1 景区路线规划 这题对刚学完概率期望的我来说简直水爆了好吗.. 因为存在时间限制,不好跑高斯消元,就直接跑dp就完了. 令 ...

  5. Python课程笔记(四)

    1.模块的导入 相当于Java的包或C语言的头文件 (1) import math s = math.sqrt(25) print(s) (2) from math import sqrt s=mat ...

  6. vim 让人爱不释手的编辑器之神

    VIM 基本介绍 vim诞生已有20多年,它常被人称之为编辑器之神,vim的操作理念可以说是独具一格而又出类拔萃,使用vim能极大的提升文本处理效率,因此熟练掌握vim应该是每个程序员都应该做到的事情 ...

  7. 关于linux的fork的一点学习总结

    最近操作系统的实验要用到fork,于是去搜索了一下资料,很幸运地在博客中找到一篇深度好文: http://blog.csdn.net/jason314/article/details/5640969 ...

  8. centos7 使用iptables

    关闭selinux,不关闭时,iptables不读取配置文件 重启生效 centos7 中默认的防火墙是firewalld,使用iptables需要先关闭firewalld防火墙,安装iptables ...

  9. CSP2020-儒略历

    大家可以在洛谷提交: 题目描述 为了简便计算,天文学家们使用儒略日(Julian day)来表达时间.所谓儒略日,其定义为从公元前 4713 年 1 月 1 日正午 12 点到此后某一时刻间所经过的天 ...

  10. CSS px的理解

    px是像素.然而一个屏幕像素的多少是由屏幕的分辨率决定的. 取个极端的栗子:如果分辨率是1w*1w,你设置一个100px宽的输入框,你只占屏幕的1/100,但是如果屏幕的分辨率是100*100,那么你 ...