go语言interface学习
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
最新文章
- EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(三)
- java.io.IOException: Cannot run program ";jad";
- Github快速入门手册
- NOIp 0904 出题报告
- [前端_EasyUI]给easyui的datebox设置默认值,获取不到 的解决方法
- UML系列05之 基本流程图
- Assets/Sciprts/GameSciprt.js(97,46): BCE0044: expecting :, found &#39;,&#39;.
- redis存储对象,实体类新加字段空指针问题处理
- BS开发平台,一小时搞定功能强大的统计分析页面
- .Net写txt文件-简单的记录执行日志信息代码
- 【shell点滴】参数变量
- Odoo免费开源ERP销售收款的财务对账解决方案
- 简单管理员权限与几个常用的PHP 常用函数,in_array(),explode(),implode(),join(),str_replace()
- JS-预解析(提升)与代码执行过程
- 小米系统获取root权限的完整教程
- java8_api_正则表达式
- [20180810]exadata--豆腐渣系统的保护神.txt
- shell 的条件表达式及逻辑操作符简单介绍
- 关于List、Map循环时,进行删除的结论
- 第十一周(11.24-12.01)----WBS功能分解
热门文章
- win7下Excel2003/2010 同时打开多个独立窗口
- Linux - 对比net-tools与iproute2
- wordpress可以自定义获取相关文章的代码
- SPSS 2019年10月31日 20:20:53今日学习总结
- golang web框架 beego 学习 (六) request body和module的映射
- 【CUDA开发】论CUDA和LAV解码器是否真的实用
- 【转】JS大总结(带实例)
- Git使用两个用户名两个公钥链接同一个Git服务器
- PCL学习(二)三维模型转点云 obj转pcd----PCL实现
- 《Mysql - SQL优化》