非零基础自学Golang
文章目录
- 非零基础自学Golang
- 第12章 接口与类型
- 12.2 接口的创建与实现
- 12.2.2 接口赋值
第12章 接口与类型
12.2 接口的创建与实现
12.2.2 接口赋值
如果用户自定义的类型实现了某个接口类型所声明的一组方法,那么这个用户定义的类型的值就可以赋值给这个接口。
这个赋值会把用户定义的类型的值存入接口类型的值。
这里涉及接口变量,
接口变量存储了两部分信息
- 一是分配给接口变量的具体值(接口实现者的值)
- 二是值的类型的描述器(接口实现者的类型)。
简单来说,接口赋值存在以下两种情况:
- 将对象实例赋值给接口;
- 将一个接口赋值给另一个接口。
当一个对象的类型是一个接口的实例时,这个对象就可以赋值给这个接口。需要注意的是,只能将对象的指针赋值给接口变量,不能将对象值直接赋值给接口变量,否则就会发生错误。
[ 动手写12.2.6]
package main
import "fmt"
type IDatabaser interface {
Connect() error
Disconnect() error
}
// Redis数据库操作
type Redis struct {
DBName string
}
func (redis *Redis) Connect() error {
fmt.Println("Redis Connect DB => " + redis.DBName)
//do Connect
fmt.Println("Redis Connect Success!")
return nil
}
func (redis *Redis) Disconnect() error {
//do Disconnect
fmt.Println("Redis Disconnect Success!")
return nil
}
func main() {
var redis = Redis{DBName: "teacher"}
var idb IDatabaser = &redis
idb.Connect()
idb.Disconnect()
}
运行结果
这就是把对象的指针赋值给接口变量。
对于第二种情况(通过一个接口给另一个接口赋值),在Go语言中只要两个接口拥有同样的方法集(次序不同不要紧),那么它们就是相同的,可以相互赋值。如果两个接口不是相同的,接口A的方法集是接口B方法集的子集,那么接口B可以赋值给接口A,反之则不成立。
举个例子:
package main
import "fmt"
type IDatabaser interface {
Connect() error
Disconnect() error
}
type IRediser interface {
Connect() error
}
// Redis数据库操作
type Redis struct {
DBName string
}
func (redis *Redis) Connect() error {
fmt.Println("Redis Connect DB => " + redis.DBName)
//do Connect
fmt.Println("Redis Connect Success!")
return nil
}
func (redis *Redis) Disconnect() error {
//do Disconnect
fmt.Println("Redis Disconnect Success!")
return nil
}
func main() {
var idb IDatabaser = &Redis{DBName: "teacher"}
var iredis IRediser
iredis = idb
iredis.Connect()
}
运行结果
没毛病,懂了!
动手写12.2.7中,IRediser接口的方法集是IDatabaser接口方法集的子集,IDatabaser接口变量就可以直接赋值给IRediser接口变量。