Golang面向API编程-interface(接口)

yinzhengjie · · 4051 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

                    Golang面向API编程-interface(接口)

                                          作者:尹正杰

版权声明:原创作品,谢绝转载!否则将追究法律责任。

 

 

 

  Golang并不是一种典型的面向对象编程(Object Oriented Programming,OOP,面向对象程序设计)语言。它在语法上不支持类和继承的概念。没有继承是否就无法拥有多态行为了呢?答案是否定的,我们知道 Golang 中没有 class 的概念,而是通过 interface 类型转换支持在动态类型语言中常见的“鸭子类型”达到运行时多态的效果。

 

一.什么是interface

  简单的说,interface是一组method的组合,我们通过interface来定义对象的一组行为。换句话说,一个 interface 类型定义了一个“方法集合”作为其接口。 interface类型的变量可以保存含有属于这个interface类型的任何类型的值,这时我们就说这个类型实现了这个接口。未被初始化的interface类型变量的零值为空(nil)。

 

二.interface类型和值

  接口类型实际上是一组method(方法)签名的清单。interface 类型定义了一组方法,如果某个对象实现了某个接口的所有方法,则此对象就实现了此接口。接口也是一种数据类型。如果你声明了一个接口变量,这个变量能够存储任何实现该接口的对象类型。最后,任意的类型都实现了空interface(我们这样定义:interface{}),也就是包含 0 个method的interface。所以我喜欢给它起一个绰号叫“大胃王”。

  定义一个interface以及调用方式如下:

 1 /*
 2 #!/usr/bin/env gorun
 3 @author :yinzhengjie
 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 5 EMAIL:y1053419035@qq.com
 6 */
 7 
 8 package main
 9 
10 import (
11     "fmt"
12     "strings"
13 )
14 
15 type Human struct {
16     Name string            //定义姓名
17     string                //内置的匿名字段,我们用它来定义家庭住址。
18     phone int            //电话号码
19 }
20 
21 type Student struct {
22     Human                 //匿名字段,其类型就是我们上面自定义的类型。
23     Classroom string    //教室名称
24     Score float64        //考试成绩
25 }
26 
27 type Teacher struct {
28     Human                 //匿名字段
29     Position string        //职位信息
30     salary float64        //薪资情况
31 }
32 
33 
34 func (h Human) SayHi() {                    //定义结构体“Human”自我介绍的方法。
35     fmt.Printf("Hello, my name is 【%s】. My phone number is【%d】.My home address is【%s】\n", h.Name,
36         h.phone,h.string)                    //格式化输出是可以换行的哟。
37 }
38 
39 
40 func (h Human) Sing(Name string) {          //定义结构体“Human”唱歌的方法
41     fmt.Printf("【%s】:我有一只小毛驴我从来也不骑,有一天我心血来潮骑它去赶集.....\n", Name)
42 }
43 
44 
45 func (t Teacher) SayHi() {                    //定义结构体“Teacher”自我介绍的方法。
46     fmt.Printf("Anyway, I'm your 【%s】 teacher, you can call me 【%s】,My salary is...【%f】\n", t.Position,
47         t.Human.Name,t.salary)
48 }
49 
50 
51 type Superman interface {                    //定义一个接口
52     SayHi()                                    //这个接口包含“SayHi()    ”方法。
53     Sing(Name string)                        //该接口也包含“Sing(Name string)”方法。
54 }
55 
56 func main() {
57     yzj := Student{Human{"尹正杰", "北京", 7474741}, "三年级一班", 95} //初始化我们定义的结构体。我们也可以将这个过程叫做实例化。而将“yzj”叫做实例。
58     hsy := Student{Human{"韩森雨", "北京", 2424241}, "一年级五班", 100}
59     bingan := Teacher{Human{"饼干", "北京", 6464641}, "Golang", 30000}
60 
61 
62     var yinzhengjie Superman  //声明一个变量,其类型为我们定义的接口。
63 
64     yinzhengjie = yzj                        //注意了,这是接受了我们定义第一个类型。
65     yinzhengjie.SayHi()                        //并且可以调用这个类型下的“SayHi()”方法已经“Sing("高音唱")”方法。
66     yinzhengjie.Sing("高音唱")
67 
68 
69     fmt.Println("\n",strings.Repeat("*",30),"我是分割线",strings.Repeat("*",30),"\n")
70 
71     yin := make([]Superman,3)    //处理上面的那种最普遍的玩法,当然也可以用make方法将其定义成切片的方式。
72     yin[0], yin[1], yin[2] = hsy, bingan, yzj //用下标来区分不同的实力。这个时候我们可以发现Superman类型可以接受“Student”和“Teacher”类型的数据,尽管这是两个不同的结构体,但是照样可以通过一个接口来调用,因此我叫它“大胃王”。
73 
74     for _, value := range yin{ //然后我们就可以同时调用3个方法啦!
75         value.SayHi()
76     }
77 }
78 
79 
80 
81 #以上代码执行结果如下:
82 Hello, my name is 【尹正杰】. My phone number is【7474741】.My home address is【北京】
83 【高音唱】:我有一只小毛驴我从来也不骑,有一天我心血来潮骑它去赶集.....
84 
85  ****************************** 我是分割线 ****************************** 
86 
87 Hello, my name is 【韩森雨】. My phone number is【2424241】.My home address is【北京】
88 Anyway, I'm your 【Golang】 teacher, you can call me 【饼干】,My salary is...【30000.000000】
89 Hello, my name is 【尹正杰】. My phone number is【7474741】.My home address is【北京】

   通过上面的代码我们可以知道,interface 可以被任意的对象实现。同理,一个对象可以实现任意多个interface。你会发现interface 就是一组抽象方法的集合,它必须由其他非interface类型实现,而不能自我实现, go 通过 interface 实现了duck-typing:即"当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子"。

 

三.空interface

   空interface(interface{})不包含任何的 method,正因为如此,所有的类型都实现了空interface。空 interface 对于描述起不到任何的作用(因为它不包含任何的 method),但是空interface 在我们需要存储任意类型的数值的时候相当有用,因为它可以存储任意类型的数值。一个函数把interface{}作为参数,那么他可以接受任意类型的值作为参数,如果一个函数返回interface{},那么也就可以返回任意类型的值。是不是瞬间就觉得interface很神奇!

 1 /*
 2 #!/usr/bin/env gorun
 3 @author :yinzhengjie
 4 Blog:http://www.cnblogs.com/yinzhengjie/tag/GO%E8%AF%AD%E8%A8%80%E7%9A%84%E8%BF%9B%E9%98%B6%E4%B9%8B%E8%B7%AF/
 5 EMAIL:y1053419035@qq.com
 6 */
 7 
 8 package main
 9 
10 import (
11     "fmt"
12     "reflect"
13 )
14 
15 func Myecho() {
16     fmt.Println("我有一只小毛驴我从来也不骑,有一天我心血来潮骑它去赶集.....")
17 }
18 
19 func main()  {
20       Name := "尹正杰"                      //我这里定义了三种不同的类型,即字符串,整数,字节数等等。
21       Age := 18
22       Language := []byte("Golang")
23       fmt.Println(reflect.TypeOf(Name),reflect.TypeOf(Age),reflect.TypeOf(Language))
24       var yinzhengjie interface{}            //定义一个空的interface,由于每种数据类型都实现了空interface。因此我们利用这个特性可以接受任意类型的数据。
25       yinzhengjie = Name                    
26       fmt.Printf("变量的值是:\033[31;1m【%v】\033[0m,其类型是:\033[31;1m【%v】\033[0m\n",yinzhengjie,reflect.TypeOf(yinzhengjie))
27       yinzhengjie = Age
28       fmt.Printf("变量的值是:\033[31;1m【%v】\033[0m,其类型是:\033[31;1m【%v】\033[0m\n",yinzhengjie,reflect.TypeOf(yinzhengjie))
29       yinzhengjie = Language
30        fmt.Printf("变量的值是:\033[31;1m【%v】\033[0m,其类型是:\033[31;1m【%v】\033[0m\n",yinzhengjie,reflect.TypeOf(yinzhengjie))
31 }
32 
33 
34 
35 #以上代码执行结果如下:
36 string int []uint8
37 变量的值是:【尹正杰】,其类型是:【string】
38 变量的值是:【18】,其类型是:【int】
39 变量的值是:【[71 111 108 97 110 103]】,其类型是:【[]uint8】

 

四.interface 函数参数

   interface 的变量可以持有任意实现该 interface 类型的对象,这给我们编写函数(包括method)提供了一些额外的思考,我们是不是可以通过定义 interface 参数,让函数接受各种类型的参数。举个例子:fmt.Println 是我们常用的一个函数,但是你是否注意到它可以接受任意类型的数据。打开fmt的源码文件,你会看到这样一个定义:

 


有疑问加站长微信联系(非本文作者)

本文来自:博客园

感谢作者:yinzhengjie

查看原文:Golang面向API编程-interface(接口)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4051 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传