设为首页 收藏本站
查看: 1395|回复: 0

[经验分享] 深入学习golang(5)

[复制链接]

尚未签到

发表于 2018-9-20 07:32:49 | 显示全部楼层 |阅读模式
接口

概述
  如果说goroutine和channel是Go并发的两大基石,那么接口是Go语言编程中数据类型的关键。在Go语言的实际编程中,几乎所有的数据结构都围绕接口展开,接口是Go语言中所有数据结构的核心。
  
Go语言中的接口是一些方法的集合(method set),它指定了对象的行为:如果它(任何数据类型)可以做这些事情,那么它就可以在这里使用。
  

type Reader interface {  Read(p []byte) (n int, err error)
  
}
  

  
type Writer interface {
  Write(p []byte) (n int, err error)
  
}
  

  
type Closer interface {
  Close() error
  
}
  

  
type Seeker interface {
  Seek(offset int64, whence int) (int64, error)
  
}
  

  上面的代码定义了4个接口。
  
假设我们在另一个地方中定义了下面这个结构体:
  

type File struct { // ...  
}
  
func (f *File) Read(buf []byte) (n int, err error)
  
func (f *File) Write(buf []byte) (n int, err error)
  
func (f *File) Seek(off int64, whence int) (pos int64, err error) func (f *File) Close() error
  

  我们在实现File的时候,可能并不知道上面4个接口的存在,但不管怎样,File实现了上面所有的4个接口。我们可以将File对象赋值给上面任何一个接口。
  

var file1 Reader = new(File)  
var file2 Writer = new(File)
  
var file3 Closer = new(File)
  
var file4 Seeker = new(File)
  

  因为File可以做这些事情,所以,File就可以在这里使用。File在实现的时候,并不需要指定实现了哪个接口,它甚至根本不知道这4个接口的存在。这种“松耦合”的做法完全不同于传统的面向对象编程。
  实际上,上面4个接口来自标准库中的io package。

接口赋值
  我们可以将一个实现接口的对象实例赋值给接口,也可以将另外一个接口赋值给接口。
  (1)通过对象实例赋值
  将一个对象实例赋值给一个接口之前,要保证该对象实现了接口的所有方法。考虑如下示例:
  

type Integer int  
func (a Integer) Less(b Integer) bool {
  return a < b
  
}
  
func (a *Integer) Add(b Integer) {
  *a += b
  
}
  

  
type LessAdder interface {
  Less(b Integer) bool
  Add(b Integer)
  
}
  

  
var a Integer = 1
  
var b1 LessAdder = &a //OK
  
var b2 LessAdder = a   //not OK
  

  b2的赋值会报编译错误,为什么呢?还记得一章中讨论的Go语言规范的规定吗?

  The method set of any other named type T consists of all methods with receiver type T. The method set of the corresponding pointer type T is the set of all methods with receiver T or T (that is, it also contains the method set of T).
  
也就是说*Integer实现了接口LessAdder的所有方法,而Integer只实现了Less方法,所以不能赋值。

  (2)通过接口赋值
  

        var r io.Reader = new(os.File)  var rw io.ReadWriter = r   //not ok
  

  var rw2 io.ReadWriter = new(os.File)
  var r2 io.Reader = rw2    //ok
  

  因为r没有Write方法,所以不能赋值给rw。

接口嵌套
  我们来看看io package中的另外一个接口:
  

// ReadWriter is the interface that groups the basic Read and Write methods.  
type ReadWriter interface {
  Reader
  Writer
  
}
  

  该接口嵌套了io.Reader和io.Writer两个接口,实际上,它等同于下面的写法:
  

type ReadWriter interface {  
Read(p []byte) (n int, err error)
  
Write(p []byte) (n int, err error)
  
}
  

  注意,Go语言中的接口不能递归嵌套,
  

// illegal: Bad cannot embed itself  
type Bad interface {
  Bad
  
}
  

  
// illegal: Bad1 cannot embed itself using Bad2
  
type Bad1 interface {
  Bad2
  
}
  
type Bad2 interface {
  Bad1
  
}
  

空接口(empty interface)
  空接口比较特殊,它不包含任何方法:
  

interface{}  

  在Go语言中,所有其它数据类型都实现了空接口。
  

var v1 interface{} = 1  
var v2 interface{} = &quot;abc&quot;
  
var v3 interface{} = struct{ X int }{1}
  

  如果函数打算接收任何数据类型,则可以将参考声明为interface{}。最典型的例子就是标准库fmt包中的Print和Fprint系列的函数:
  

func Fprint(w io.Writer, a ...interface{}) (n int, err error)  
func Fprintf(w io.Writer, format string, a ...interface{})
  
func Fprintln(w io.Writer, a ...interface{})
  
func Print(a ...interface{}) (n int, err error)
  
func Printf(format string, a ...interface{})
  
func Println(a ...interface{}) (n int, err error)
  

  注意,[]T不能直接赋值给[]interface{}
  

        t := []int{1, 2, 3, 4}  var s []interface{} = t
  

  编译时会输出下面的错误:

  cannot use t (type []int) as type []interface {} in assignment

  我们必须通过下面这种方式:
  

t := []int{1, 2, 3, 4}  
s := make([]interface{}, len(t))
  
for i, v := range t {
  s = v
  
}
  

类型转换(Conversions)
  类型转换的语法:
  

Conversion = Type &quot;(&quot; Expression [ &quot;,&quot; ] &quot;)&quot; .  

  当以运算符*或者

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-597742-1-1.html 上篇帖子: Golang的文件处理方式 下篇帖子: golang--使用channel来同步goroutine
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表