本篇内容主要讲解“go语言可不可以开发接口”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“go语言可不可以开发接口”吧!
go语言可以开发接口。go语言中接口是一组方法的签名,它是go语言中重要的组成部分,接口做的事情就好像是定义一个规范或者协议,各个实现方只要按照协议实现即可。go语言中使用interface关键字来定义接口,语法“type 接口类型名 interface{方法名1( 参数列表1 ) 返回值列表1 方法名2( 参数列表2 ) 返回值列表2…}”。
接口对于我们来说应该是一个比较熟悉的概念,在各种开发语言中运用都非常的广泛,对于像我们比较熟悉java的程序员来说对于接口就更加的亲切,下面我们来看下在go语言中接口是怎么用,以及接口在日常开发中发挥的作用。
go语言中接口是一组方法的签名,它是go语言中重要的组成部分,接口做的事情就好像是定义一个规范或者协议,各个实现方只要按照协议实现即可。
接口是一种类型
接口类型是对其他类型行为的抽象和概括,不关心具体的实现细节,这种抽象的方式可以让我们的函数变的更加灵活。
type 接口类型名 interface{
方法名1( 参数列表1 ) 返回值列表1
方法名2( 参数列表2 ) 返回值列表2
…
}
在go语言中我们使用interface关键字来定义接口。
如果一个任意类型T的方法集为一个接口类型的方法集的超集,则我们说类型T实现了该接口。
接口的实现在go语言中是隐式的,也就说两个类型之间的实现关系不需要在代码中体现出来,G哦语言中也没有类似java中implements的关键字,Go编译器将自动在需要的时候检查两个类型之间的实现关系。接口定义后,需要实现接口,调用方才能正确编译通过并使用接口。
接口的实现需要遵循两条规则才能让接口可用:
1、接口的方法与实现接口的类型方法格式一致在类型中添加与接口签名一致的方法就可以实现该方法。签名包括方法中的名称、参数列表、返回参数列表。也就是说,只要实现接口类型中的方法的名称、参数列表、返回参数列表中的任意一项与接口要实现的方法不一致,那么接口的这个方法就不会被实现。
package main
import "fmt"
type Phone interface {
Call()
SendMessage()
}
type HuaWei struct {
Name string
Price float64
}
func (h *HuaWei) Call() {
fmt.Printf("%s:可以打电话",h.Name)
}
func (h *HuaWei) SendMessage() {
fmt.Printf("%s:可以发送短信",h.Name)
}
func main() {
h := new(HuaWei)
h.Name="华为"
var phone Phone
phone = h
phone.SendMessage()
}
当类型无法实现接口时,编译器会报错:
a.函数名称不一致导致的报错
b.实现函数的方法签名不一致导致的报错
2、接口中所有方法均被实现当一个接口中有多个方法时,只有这些方法都被实现了,接口才能被正确编译并使用
func (h *Xiaomi) Call() {
fmt.Printf("%s:可以打电话",h.Name)
}
func main() {
h := new(Xiaomi)
h.Name="小米"
var phone Phone
phone = h
phone.SendMessage()
}
当 小米 类型仅仅实现接口中的一个方法的时候,我们在使用的时候,编译报错。
一个类型实现多个接口
一个类型可以实现多个接口,而接口之间彼此独立,不知道对方的实现。
例如,狗既可以动,可以叫
package main
import "fmt"
type Move interface {
move()
}
type Say interface {
say()
}
type Dog struct {
Name string
}
func (d *Dog) move() {
fmt.Printf("%s会动\n", d.Name)
}
func (d *Dog) say() {
fmt.Printf("%s会叫汪汪汪\n", d.Name)
}
func main() {
var m Move
var s Say
d:=&Dog{
Name: "旺财",
}
m = d
s=d
m.move()
s.say()
}
多个类型实现同一个接口
Go语言中不同的类型还可以实现同一接口 首先我们定义一个Mover接口,它要求必须有一个move方法。
type Mover interface {
move()
}
例如狗可以动,汽车也可以动,可以使用如下代码实现这个关系:
type dog struct {
name string
}
type car struct {
brand string
}
// dog类型实现Mover接口
func (d dog) move() {
fmt.Printf("%s会跑\n", d.name)
}
// car类型实现Mover接口
func (c car) move() {
fmt.Printf("%s速度70迈\n", c.brand)
}
这个时候我们在代码中就可以把狗和汽车当成一个会动的物体来处理了,不再需要关注它们具体是什么,只需要调用它们的move方法就可以了。
func main() {
var x Mover
var a = dog{name: "旺财"}
var b = car{brand: "保时捷"}
x = a
x.move()
x = b
x.move()
}
空接口:interface{},不包含任何方法,正因为如此,任何类型都实现了空接口,所以空接口可以存储任意类型的数据。
fmt
包下的 Print
系列函数,其参数大多是空接口类型,也可以说支持任意类型
func Print(a ...interface{}) (n int, err error)
func Println(format string, a ...interface{}) (n int, err error)
func Println(a ...interface{}) (n int, err error)
空接口作为map的值
// 空接口作为map值
var studentInfo = make(map[string]interface{})
studentInfo["name"] = "李白"
studentInfo["age"] = 18
studentInfo["married"] = false
fmt.Println(studentInfo)
空接口可以存储任意类型的值,那我们如何获取其存储的具体数据呢?
接口值
一个接口的值(简称接口值)是由一个具体类型和具体类型的值两部分组成的。
这两部分分别称为接口的动态类型和动态值。
想要判断空接口中的值这个时候就可以使用类型断言,其语法格式:
x.(T)
其中:
x:表示类型为interface{}的变量
T:表示断言x可能是的类型。
该语法返回两个参数,第一个参数是x转化为T类型后的变量,第二个值是一个布尔值,若为true则表示断言成功,为false则表示断言失败。
func main() {
var x interface{}
x = "ms的go教程"
v, ok := x.(string)
if ok {
fmt.Println(v)
} else {
fmt.Println("类型断言失败")
}
}
上面的示例中如果要断言多次就需要写多个if判断,这个时候我们可以使用switch语句来实现:
func justifyType(x interface{}) {
switch v := x.(type) {
case string:
fmt.Printf("x is a string,value is %v\n", v)
case int:
fmt.Printf("x is a int is %v\n", v)
case bool:
fmt.Printf("x is a bool is %v\n", v)
default:
fmt.Println("unsupport type!")
}
}
因为空接口可以存储任意类型值的特点,所以空接口在Go语言中的使用十分广泛。
到此,相信大家对“go语言可不可以开发接口”有了更深的了解,不妨来实际操作一番吧!这里是亿速云网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。