Go 语言提供了另外一种数据类型即接口,它把所有的具有共性的方法定义在一起,简单的说,interface是一组method的组合,我们通过interface来定义对象的一组行为,任何其他类型只要实现了这些方法就是实现了这个接口,这也是Go最精妙的部分,它让面向对象,内容组织实现非常的方便。Go的接口和PHP的接口很像,关键字都是interface。
package main
import (
"fmt"
)
//声明一个USB的接口
type USB interface {
Name() string
Connect()
}
//声明一个PhoneConnect的结构去实现USB接口
type PhoneConnecter struct {
name string
}
func (pc PhoneConnecter) Name() string {
return pc.name
}
func (pc PhoneConnecter) Connect() {
fmt.Println(pc.Name(), "已经成功连接")
}
//注意:我们所说的首字母大小写的公私有权限问题,是针对包外的,即除了该main包意外的包,而在包里不管大小写都是可以访问的
func main() {
var a USB //声明a的类型是USB类型
a = PhoneConnecter{"森森的电脑"} //成功实现USB接口
a.Connect()
}
输出:
森森的电脑 已经成功连接
package main
import (
"fmt"
)
//声明一个USB的接口
type USB interface {
Name() string
Connecter //嵌入Connecter,从而USB就拥有Connecter的方法Connect()
}
type Connecter interface {
Connect()
}
//声明一个PhoneConnect的结构去实现USB接口
type PhoneConnecter struct {
name string
}
func (pc PhoneConnecter) Name() string {
return pc.name
}
func (pc PhoneConnecter) Connect() {
fmt.Println(pc.Name(), "已经成功连接")
}
func main() {
var a USB //声明a的类型是USB类型
a = PhoneConnecter{"森森的电脑"} //成功实现USB接口
a.Connect()
Disconnect(a)
}
func Disconnect(usb USB) {
//判断类型,判断usb是个什么结构
//通过类型断言的ok pattern可以判断接口中的数据类型
if pc, ok := usb.(PhoneConnecter); ok { //这里不要忘了加括号,如果OK为true,说明传进来的usb是PhoneConnecter结构,则可以调用name属性,获得名字
fmt.Println(pc.Name(), "已经断开连接")
return
}
fmt.Println("未知设备")
}
输出:
森森的电脑 已经成功连接
森森的电脑 已经断开连接
森森的电脑 已经断开连接
package main
import (
"fmt"
)
//声明一个USB的接口
type USB interface {
Name() string
Connecter //嵌入Connecter,从而USB就拥有Connecter的方法Connect()
}
type Connecter interface {
Connect()
}
//声明一个PhoneConnect的结构去实现USB接口
type PhoneConnecter struct {
name string
}
func (pc PhoneConnecter) Name() string {
return pc.name
}
func (pc PhoneConnecter) Connect() {
fmt.Println(pc.Name() + "已经成功连接")
}
func main() {
var a USB //声明a的类型是USB类型
a = PhoneConnecter{"森森的电脑"} //成功实现USB接口
a.Connect()
Disconnect(a)
}
func Disconnect(usb interface{}) { //这里的参数是空接口,所以可以所有的参数
//当有空接口时,一般选用switch语句,使用type switch则可针对空接口进行比较全面的类型判断
switch v := usb.(type) { //传个type,让系统自动去判断
case PhoneConnecter: //注意这里不能加双引号,否则会报错,"PhoneConnecter" (type untyped string) is not a type,不是type型
fmt.Println(v.Name() + "已经断开连接")
default:
fmt.Println("未知设备")
}
}
输出:
森森的电脑已经成功连接
森森的电脑已经断开连接
package main
import (
"fmt"
)
//声明一个USB的接口
type USB interface {
Name() string
Connecter //嵌入Connecter,从而USB就拥有Connecter的方法Connect()
}
type Connecter interface {
Connect()
}
//声明一个PhoneConnect的结构去实现USB接口
type PhoneConnecter struct {
name string
}
func (pc PhoneConnecter) Name() string {
return pc.name
}
func (pc PhoneConnecter) Connect() {
fmt.Println(pc.Name() + "已经成功连接")
}
//TVConnecter只实现Connecter,没有实现USB,所以只能调用Connect()方法,因此转换成USB时会报错
type TVConnecter struct {
name string
}
func (tv TVConnecter) Connect() {
fmt.Println(tv.Name() + "已经成功连接")
}
func main() {
tv := TVConnecter{"森森的电视"}
var a USB
a = USB(tv) //报错:cannot convert tv (type TVConnecter) to type USB:
a.Connect()
}
输出:
.\hello.go:42:9: cannot convert tv (type TVConnecter) to type USB:
TVConnecter does not implement USB (missing Name method)
package main
import (
"fmt"
)
//只有当接口存储的类型和对象都为nil时,接口才等于nil
func main() {
var a interface{} //空接口a
fmt.Println(a) //a什么都没有,就是nil
fmt.Println(a == nil) //空接口a,什么都没存,说明他是等于nil
var p *int = nil //执行int的指针p,赋值为nil
a = p //a指向p,指向的对象是个nil,但是存在类型不是nil,是个指针
fmt.Println(a)
fmt.Println(a == nil) //因此为false
}
输出:
<nil>
true
<nil>
false