分享
  1. 首页
  2. 文章

go - interface 接口

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

Interface

1. 概述
Interface 是一组抽象方法(未具体实现的方法/仅包含方法名参数返回值的方法)的集合,有点像但又不同于其他编程语言中的 interface 。
如果实现了 interface 中的所有方法,即该类/对象就实现了该接口

2. interface 类型
格式:
type interfaceName interface {
 //方法列表
}
注:
a. interface 可以被任意对象实现,一个类型/对象也可以实现多个 interface
b. 方法不能重载,如 eat() eat(s string) 不能同时存在

3. interface 值
声明为 interface 类型的变量,可以存储任何实现了 interface 中所有方法的类型的变量(对象)
注:类的值类型传递方法会自动生成对应的引用类型传递方法,反之不成立

4. interface 组合
将一个 interface1 嵌入到另一个 interface2 的声明中
其作用相当于把 interface1 的函数包含到 interface2 中,但是组合中不同有重复的方法
注:
a. 只要两个接口中的方法列表相同(与顺序无关),即为相同的接口,可以相互赋值
b. interface1 的方法列表属于另一个 interface2 的方法列表的子集,interface2 可以赋值给 interface1,反之不成立(因为方法缺失),interface2 中的方法会覆盖 interface1 中同名的方法
c. 可以嵌入包中的 interface

5. interface 查询
通过查询可以判断接口它指向的对象是否为某个类型
通过查询可以将原本为子集的 interface1 转为 interface2 类型,即 interface1 就可以调用原本属于 interface2 独有的方法
常见用法:
 if varName2, ok := varName1.(interface2|typeName); ok {
 //此时 varName2 的类型由 interface1 转为 interface2,或者 varName1 不是 typeName 类型的变量
 } else {
 //不能转换 interface,或者 varName1 不是 typeName 类型的变量
 }
注:
a. varName2 保存 varName1 值,varName1 为 interface 变量, () 中为类型
b. varName.(type) 用于判断类型,不能用于 switch 外的逻辑中,此处的 type 关键字

示例程序:
package main
import "fmt"
type Person struct {
	name string
	age int
}
func (p Person) printMsg() {
	fmt.Printf("I am %s, and my age is %d.\n", p.name, p.age)
}
func (p Person) eat(s string) {
	fmt.Printf("%s is eating %s ...\n", p.name, s)
}
func (p Person) drink(s string) {
	fmt.Printf("%s is drinking %s ...\n", p.name, s)
}
type People interface {
	printMsg()
	PeopleEat //组合
	PeopleDrink
	//eat() //不能出现重复的方法
}
/*
//与上面等价
type People interface {
	printMsg()
	eat()
	drink()
}
*/
type PeopleDrink interface {
	drink(s string)
}
type PeopleEat interface {
	eat(s string)
}
type PeopleEatDrink interface {
	eat(s string)
	drink(s string)
}
//以上 Person 类[型]就实现了 People/PeopleDrink/PeopleEat/PeopleEatDrink interface 类型
type Foodie struct {
	name string
}
func (f Foodie) eat(s string) {
	fmt.Printf("I am foodie, %s. My favorite food is the %s.\n", f.name, s)
}
//Foodie 类实现了 PeopleEat interface 类型
func main() {
	//定义一个 People interface 类型的变量p1
	var p1 People
	p1 = Person{"Rain", 23}
	p1.printMsg() //I am Rain, and my age is 23.
	p1.drink("orange juice")//print result: Rain is drinking orange juice
	//同一类可以属于多个 interface, 只要这个类实现了这个 interface中的方法
	var p2 PeopleEat
	p2 = Person{"Sun", 24}
	p2.eat("chaffy dish")//print result: Sun is eating chaffy dish ...
	//不同类也可以实现同一个 interface
	var p3 PeopleEat
	p3 = Foodie{"James"}
	p3.eat("noodle")//print result: I am foodie, James. My favorite food is the noodle
	//interface 赋值
	p3 = p1 //p3 中的方法会被 p1 中的覆盖
	p3.eat("noodle")
	/************************************/
	/*print result */
	/*Rain is eating noodle ... */
	/************************************/
	//interface 查询
	//将(子集) PeopleEat 转为 People 类型
	if p4, ok := p2.(People); ok {
		p4.drink("water") //调用 People interface 中有而 PeopleEat 中没有的方法
		fmt.Println(p4)
	}
	/************************************/
	/*print result */
	/*Sun is drink water ... */
	/*{Sun 24} */
	/************************************/
	//查询 p2 是否为 Person 类型变量
	if p5, ok := p2.(Person); ok {
		fmt.Println(p5, "type is Person")
		p5.drink("***") //此时也可以调用 Person 所有的方法
	}
	/************************************/
	/*print result */
	/*{Sun 24} type is Person */
	/*Sun is drink *** ... */
	/************************************/
	var p6 PeopleEat = Foodie{"Tom"}
	if p7, ok := p6.(People); ok {
		fmt.Println(p7)
	} else {
		fmt.Println("Error: can not convert")
	}
	//result: Error: can not convert
	if p8, ok := p6.(Foodie); ok {
		fmt.Println(p8, "type is Foodie")
	}
	//result: {Tom} type is Foodie
}

运行结果:
I am Rain, and my age is 23.
Rain is drinking orange juice ...
Sun is eating chaffy dish ...
I am foodie, James. My favorite food is the noodle.
Rain is eating noodle ...
Sun is drinking water ...
{Sun 24}
{Sun 24} type is Person
Sun is drinking *** ...
Error: can not convert
{Tom} type is Foodie


6. 空接口
空接口,无方法,即 interface{},可以代表任何类型,有点类似于 java 中的 Object 类
可以作为任何形参和返回类型,mixed
例:
//interface{}
var i interface{} = 100
var s interface{} = "hello"
fmt.Printf("i = %d, s = %s\n", i, s)
s = i
fmt.Printf("i = %d, s = %d\n", i, s)
结果:
i = 100, s = hello

i = 100, s = 100


版权声明:本文为博主原创文章,未经博主允许不得转载。


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

本文来自:CSDN博客

感谢作者:chuangrain

查看原文:go - interface 接口

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

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

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏