一文了解 Go 接口
如果本文对你有帮助,不妨点个赞,如果你是 Go 语言初学者,不妨点个关注,一起成长一起进步,如果本文有错误的地方,欢迎指出
接口
在 Go 语言中,接口是一种抽象的类型,是一组方法的集合。接口存在的目的是定义规范,而规范的细节由其他对象去实现。我们来看一个例子:
import "fmt"
type Person struct {
Name string
}
func main() {
person := Person{Name: "cmy"}
fmt.Println(person) // {cmy}
}
上述代码定义了结构体 Person ,main 函数创建了此结构体的变量 person,然后通过 fmt 包里的 Println 函数打印这个结构体,打印结果为 {cmy}。在此基础上,我们改造一下代码:
import "fmt"
type Person struct {
Name string
}
func (p Person) String() string {
return fmt.Sprintf("name: %s", p.Name)
}
func main() {
person := Person{Name: "cmy"}
fmt.Println(person) // name: cmy
}
新改造的代码里为结构体 Person 添加一个结构体方法 String() string,方法的返回结果是对 name 进行格式化,我们再打印一下结构体,观察结果发现是 String() 方法返回的值,而不是 {cmy}。
为什么是这样呢?这是因为 fmt.Println(T) 函数的实现细节里,会对结构体进行判断,如果结构体实现了 Stringer 接口,则会直接打印 String() 方法的返回值。以下是 Stringer 接口的代码:
type Stringer interface {
String() string
}
结构体实现了这个接口,也就意味着遵守这个接口所定义的规范,fmt.Println(T) 函数发现结构体有这个规范,因此就会根据规范来打印信息。基于 Stringer 接口,我们来看看接口的语法格式:
type XXX interface {
// methods
}
1、type
接口的声明,必须以 type 关键字开头。
2、接口名
推荐驼峰式命名法,首字母大写的方法名可以在包外访问,小写的只能在包内访问。
3、interface
接口的标识。
4、接口体
大括号里面声明规范,也就是声明方法,方法必须具有名字。
接口的实现
在 Go 语言里,接口的实现不是基于接口,而是基于方法。如果一个自定义类型拥有了某个接口的所有方法,那么这个自定义类型就实现这个接口。接口的实现在上述的例子中有所体现,Person 结构体定义了 String() string 方法,拥有了 Stringer 接口的所有方法,因此实现了 Stringer 接口。
一个自定义类型可以实现多个接口
接口类型变量
一旦接口被定义,它就可以用于声明变量。
import "fmt"
type A interface {
}
func main() {
var a A
fmt.Println(a) // <nil>
}
如果只声明接口变量,不初始化,变量的值默认为 nil,因为接口类型实际上是一个指针。若为接口赋初值,需要选择一个合法的值,即被赋值的基类必须实现这个接口。
空接口
在 Go 语言里面可以认为所有类型实现了空接口,因为空接口没有任何的方法。
import "fmt"
type EmptyInterface interface {
}
func main() {
var a EmptyInterface = 1
var b EmptyInterface = true
var c EmptyInterface = "hello"
var d EmptyInterface = 3.14
var e EmptyInterface = 'c'
fmt.Println(a, b, c, d, e) // 1 true hello 3.14 99
}
所有类型都实现空接口,因此空接口变量可以被赋初值为任意类型的值或变量。
类型断言
Go 语言支持类型断言操作,通过这个操作,可以还原接口变量的右值(被赋的初值)。类型断言的语法形式通常为:
v, ok := a.(T)
如果断言成功,那么 v 的值为接口变量的值,ok 的值为 true;如果断言失败,v 的值为 T 类型的零值,ok 的值为 false。
类型断言变种 type switch
通过 type switch 的方式,可以判断接口变量属于哪种动态类型。
import "fmt"
type EmptyInterface interface {
}
func main() {
var a EmptyInterface = 1
switch a.(type) {
case string:
fmt.Println("a 的右值类型为 string")
case int:
fmt.Println("a 的右值类型为 int")
case bool:
fmt.Println("a 的右值类型为 bool")
case float64:
fmt.Println("a 的右值类型为 float64")
}
}
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!