接口类型变量

Go是强类型语言,你不能将整数值赋值给浮点型变量。同样,也不能将没有实现接口的类型值赋值给接口类型变量。

// 1.定义变量是接口类型
var w io.Writer
// 2.将具体类型的值 赋值给这个变量, 要求这个具体类型实现了接口的所有方法
w = os.Stdout
w = new(bytes.Buffer)
w = time.Second // compile error: time.Duration 没有 var rwc io.ReadWriteCloser
rwc = os.Stdout
rwc = new(bytes.Buffer) // compile error: *bytes.Buffer lacks Close method // 等式右边是接口类型
w = rwc
rwc = w // compile error: io.Writer lacks Close method

关于一个类型持有一个方法的规则

  • T类型的值不持有*T指针的方法
  • *T指针的值持有T类型的方法

所以可能会有*T指针值可以赋值为某接口类型变量而T类型的值不可以的情况

type myWriter struct {}

func (m *myWriter) Write(p []byte) (n int, err error) {
return
} func main() {
var w io.Writer
w = myWriter{} // compile error: Cannot use 'myWriter{}' (type myWriter) as the type io.Writer Type does not implement 'io.Writer' as the 'Write' method has a pointer receiver
w = &myWriter{} // OK
}

接口类型封装和隐藏具体类型和它的值

接口变量会限制自己只能调用接口类型声明的方法,即便该变量被赋予的值原本有其他方法和成员变量,也无法调用

type myWriter struct {
scope string
} func (m *myWriter) Write(p []byte) (n int, err error) {
return
} func (m *myWriter) Func() {
return
} func main() {
my := &myWriter{"cn"}
fmt.Println(my.scope) // OK
my.Func() // Ok
var w io.Writer
w = my
fmt.Println(w.scope) // compile error: w.scope undefined
w.Func() // compile error: w.Func undefined
}

这样的限定就像是对实参进行了一层安全包装,函数内部只知道实参是接口类型,并不知道其他的信息,也无法访问。

从之前的例子可以看到,大接口变量可以被赋值给小接口,被赋值后小接口也只能调用小接口的方法。

空接口存在的意义

空接口(interface{})即没有声明任何方法的接口。因为它什么都没有,所以它可以成为任何。

package main

import (
"bytes"
"fmt"
) func emptyInterfaceIsAny() {
var any interface{}
any = true
fmt.Println(any)
any = 12.34
fmt.Println(any)
any = "hello"
fmt.Println(any)
any = map[string]int{"one": 1}
fmt.Println(any)
any = new(bytes.Buffer)
fmt.Println(any)
}

这很有用,fmt.Println方法就是通过定义参数是空接口类型,才能接收任务类型的实参传递

package main

import "fmt"

func printlnArgsIsEmptyInterface() {
fmt.Println(1, "hello", []string{"world"}) // 1 hello [world]
}

合理定义接口

接口是对一些有着相同属性实体抽象。那对一些相同属性定义是仁者见仁智者见智,评判抽象的好与坏的标准即:这个接口类型的使用者是否舒服、被使用的次数多不对。

文中展示的例子是对数字文化产品(如:音乐、电影和书籍)的抽象。

其中对音乐和电影抽象出的Streamer值得思考

type Streamer interface {
Stream() (io.ReadCloser, error)
RunningTime() time.Duration
Format() string
}

每个具体类型基于他们实现接口声明的所有方法隐式地实现了接口。在Go语言中我们可以在需要的时候定义一个新的抽象或者特定特点的组,而不需要修改具体类型的定义。

最新文章

  1. JS-sort排序
  2. Windows Azure HandBook (2) Azure China提供的服务
  3. TCP_NODELAY
  4. 安卓开发笔记——自定义HorizontalScrollView控件(实现QQ5.0侧滑效果)
  5. js判断页面点击事件
  6. js简单的工厂模式
  7. JVM的GC理论详解
  8. SublimeText快捷键大全(附GIF演示图)
  9. ubuntu修改主机名称
  10. iframe页面改动parent页面的隐藏input部件value值,不能触发change事件。
  11. 高效率dc升壓轉換器 應用技巧談 功率設計
  12. drawBitmapMesh方法关键参数的说明
  13. Just do it!!!
  14. JavaSE(十二)之IO流的字节流(一)
  15. SQL中笛卡尔积-cross join的用法
  16. 两个1/x类的广义函数
  17. Mac下安装Mysql以及修改Mysql密码
  18. HashMap怎样解决碰撞问题
  19. SSH 连接很慢
  20. hadoop2.7节点的动态增加与删除

热门文章

  1. selenium3 + python - js&jquery操作处理
  2. React构建组件的方式
  3. PAT甲级:1036 Boys vs Girls (25分)
  4. 最大流最小割——bzoj1001狼抓兔子,洛谷P2598
  5. mysql常用sql语法
  6. 项目启动报错 The server time zone value '�й���׼ʱ��' is unrecognize...
  7. MySql查询上周(周一到周日)每天的日期!土方!
  8. time() 在thinkphp 3.2.3 模板格式化输出
  9. MSTP
  10. 电脑常用快捷键及常用的DOS命令