Go 中的 interface 所具有的最基本的功能:作为一种 abstract type,实现各种 concrete type 的行为统一。

interface是一种类型。只有是实例化后才能调用interface中的方法,没毛病。

interface的定义

基本形式如下;

 type (reciever *T) FUNC_NAME (args)  (args...Type) {
//do something
}

interface内部由0个或者多个方法声明组成:

 /* interface可以没有方法声明 */
type USB interface {
} /* 多个method声明 */
type USB interface {
Name()
Age()
User()
}

也可以嵌套别的interface组合成一个新的interface:

 type USB interface {
Name() string
} type Computer interface {
USB
screen(price int)
}

以上几种方式都是等价的,但是更推崇嵌入的方式。想下为什么?为了更好的实现多态啊。后面讲。

interface的内部实现初探?

我先实例化上面的interface,然后看一下他所占用的内存大小:(我是在64位操作系统上跑的)

 var a Computer
fmt.Println("sizeof computer = ", unsafe.Sizeof(a))
/* vsizeof computer = 16 */

实际上,所有的interface实例化后都是一样的大小16字节(64位机)。为什么呢?说明interface存放的是一个固定结构,不然大小肯定会变化,就像任何指针变量在64位机上都占8个字节一样。

interface存储的是实例化的值

 /* declare In interface */
type In interface {
Name() string
} /* declare S struct */
type S struct {
x int32
y int32
} /* implement method Name() string with S struct;
* Now S struct is an instance of In interface
*/
func (s S) Name() string {
return "interface"
} /* function print
* we can pass an instance of in interface,
* we can pass an instance of S struct, too
*/
func print(in In) {
fmt.Println(in.Name())
} func main() {
s := S{}
print(s) //ok var i In
i = s
print(i) //ok
}

interface的重要作用体现在func print(in In)中。如果有多种struct实现了interface的methods,那么以interface为接收类型的函数可以接收所有实现了其方法的对象。

这点有点像C++中的父类指针可以接收子类实例作为参数的用法,C++这种做法实现了运行时的多态。

go和C++有所不同的是,go语言不需要显式的告诉编译器我实现了哪些interface,只需要隐式的默默的去实现某个或某些interface的方法即可。go程序运行时候会自动检查并转换。

注意:switch i.(type)语句结构中不能用fallthrough,具体原因不明,有待深入理解。下面这段代码编译会报错:

 switch value.(type) {
case int:
fallthrough  //error
case int64:
//......
}

并列写就不会报错了:

 switch value.(type) {
case int, int64:    //ok
//......
case int int32:
//......
}

空interface

go语言和java一样,支持empty interface。看一下下面代码的执行:

 func main() {
var any interface{}
any = 1
fmt.Println(any) //
any = nil
fmt.Println(any) //<nil>
any = "string"
fmt.Println(any) //string
any = S{}
fmt.Println(any) //{0 0}
}

空的interface没有声明方法,所以所有的类型都实现了interface{},因此所有类型的instance都能当参数传给interface{}的实例。

这个例子还能看出一个奥妙:

不同的类型,实现了同一个接口,那么如果一个类型的方法是另一个方法的子集,那么可以把大的赋值给小的(是赋值还是引用?要进步深入)。

interface的内部实现再探

既然空的 interface 可以接受任何类型的参数,那么一个 interface{}类型的 slice 是不是就可以接受任何类型的 slice ?

 s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
ss := make([]interface{}, len(s))
ss=s /* error*/
//cannot use s (type []int) as type []interface {} in assignment

竟然报错!!!!go为啥不自动将int转换成interface{}呢?

参考:

Go Data Structures: Interfaces

go语言interface学习的更多相关文章

  1. D01-R语言基础学习

    R语言基础学习——D01 20190410内容纲要: 1.R的下载与安装 2.R包的安装与使用方法 (1)查看已安装的包 (2)查看是否安装过包 (3)安装包 (4)更新包 3.结果的重用 4.R处理 ...

  2. C语言课程学习的总结

    C语言课程学习的总结 学习C程序这门课一年了,这是我们学的第一门专业课.在大学里,C语言不但是计算机专业的必修课程而且也是非计算机专业学习计算机基础的一门必修课程.所以作为我这个计算机专业的学生来说当 ...

  3. [转]C语言指针学习经验总结浅谈

    指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...

  4. C语言(函数)学习之strstr strcasestr

    C语言(函数)学习之[strstr]&[strcasestr]一.strstr函数使用[1]函数原型char*strstr(constchar*haystack,constchar*needl ...

  5. 【Go语言】学习资料

    这段时间一直在看Go语言,6月3日Apple发布了swift发现里面竟然也有许多Go语言的影子,截至现在每天都在感觉到Go语言的强大.确实值得一学 今天在这里给园友们推荐一些Go语言的学习资料 网站 ...

  6. 远离go path,弃用go get,使用go mod 进行go语言的学习

    标题说的是go语言的学习,因为我也没做过开发 文章要解决的仅仅是一个问题 当你使用go get 无论如何get不到所需的包的问题 第一步就是下载goland 新手极其推荐goland,因为直接使用gl ...

  7. Dart语言快速学习上手(新手上路)

    Dart语言快速学习上手(新手上路) // 声明返回值 int add(int a, int b) { return a + b; } // 不声明返回值 add2(int a, int b) { r ...

  8. D02-R语言基础学习

    R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...

  9. C++语言的学习环境

    一.Mac C++语言的学习环境 1. 1.1.C语言 :终端->bash-vi/vim文本编辑器->GNU->GCC文件编译器->a.out可执行文件 1.2.C++语言:终 ...

随机推荐

  1. 基于pythonselect.select模块通信的实例讲解

    基于python select.select模块通信的实例讲解 要理解select.select模块其实主要就是要理解它的参数, 以及其三个返回值. select()方法接收并监控3个通信列表, 第一 ...

  2. ClientDataSet中修改,删除,添加数据和Delta属性

    ClientDataSet中使用Post提交变更的数据时,实际上并没有更新到后端数据库中,而是提交到了由DataSnap管理的数据缓冲区中.当使用了ClientDataSet.ApplyUpDates ...

  3. Zabbix之设置监控主机某个端口并发送邮件告警

    Zabbix可以配置监控主机的某个端口在该端口down之后触发发送告警邮件 一,添加监控项 选择主机 监控项 创建监控项 查看监控图形 二,设置触发器 设置触发器当该监控的端口down时可以发送告警 ...

  4. charles 工具菜单总结

    本文参考:charles 工具菜单总结 主要是下面的功能,具体可以点击对应菜单查看 工具菜单总结 禁用缓存 禁用Cookies 远程映射到URL地址 映射到本地 重写工具 黑名单 白名单 DNS欺骗 ...

  5. 安装CCS提示错误Windows8.1-KB2999226-x64安装提示 此更新不适用你的计算机

    问题如图所示: 解决方案: 放在D:\目录下 windows键+X  选择  命令提示符(管理员)  一定要是管理员 打开cmd 分别执行下面两句.红色部分就是自己的更新程序了.其他安装同理 例如Wi ...

  6. [转帖]CentOS 8.0.1905 和CentOS Stream(滚动发行)正式发布

    CentOS 8.0.1905 和CentOS Stream(滚动发行)正式发布 https://zhuanlan.zhihu.com/p/84001292 还发现openssl 的 版本太高 不兼容 ...

  7. appium desired_caps参数大全

    appium desired_caps参数大全 --------------------------------------------------------- 常用参数记录 ----------- ...

  8. Java的设计模式(2)--单例模式

    保证一个类仅有一个实例,并提供一个访问它的全局访问点. 好处:    (1)频繁使用的对象,可以省略new操作花费的时间,这对于那些重量级对象而言,是非常客观的一笔开销.    (2)由于new的次数 ...

  9. 开源定时任务框架Quartz(二)

    概述 上一篇文章完成了第一个Quartz程序的编写,这篇从Quartz中的几个重要对象来更深一层认识Quartz框架. Job和JobDetail Job是Quartz中的一个接口,接口下只有exec ...

  10. ARTS第九周打卡

    Algorithm : 做一个 leetcode 的算法题 /* 两数之和 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. ...