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

最新文章

  1. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(三)
  2. java.io.IOException: Cannot run program &quot;jad&quot;
  3. Github快速入门手册
  4. NOIp 0904 出题报告
  5. [前端_EasyUI]给easyui的datebox设置默认值,获取不到 的解决方法
  6. UML系列05之 基本流程图
  7. Assets/Sciprts/GameSciprt.js(97,46): BCE0044: expecting :, found &#39;,&#39;.
  8. redis存储对象,实体类新加字段空指针问题处理
  9. BS开发平台,一小时搞定功能强大的统计分析页面
  10. .Net写txt文件-简单的记录执行日志信息代码
  11. 【shell点滴】参数变量
  12. Odoo免费开源ERP销售收款的财务对账解决方案
  13. 简单管理员权限与几个常用的PHP 常用函数,in_array(),explode(),implode(),join(),str_replace()
  14. JS-预解析(提升)与代码执行过程
  15. 小米系统获取root权限的完整教程
  16. java8_api_正则表达式
  17. [20180810]exadata--豆腐渣系统的保护神.txt
  18. shell 的条件表达式及逻辑操作符简单介绍
  19. 关于List、Map循环时,进行删除的结论
  20. 第十一周(11.24-12.01)----WBS功能分解

热门文章

  1. win7下Excel2003/2010 同时打开多个独立窗口
  2. Linux - 对比net-tools与iproute2
  3. wordpress可以自定义获取相关文章的代码
  4. SPSS 2019年10月31日 20:20:53今日学习总结
  5. golang web框架 beego 学习 (六) request body和module的映射
  6. 【CUDA开发】论CUDA和LAV解码器是否真的实用
  7. 【转】JS大总结(带实例)
  8. Git使用两个用户名两个公钥链接同一个Git服务器
  9. PCL学习(二)三维模型转点云 obj转pcd----PCL实现
  10. 《Mysql - SQL优化》