非零基础自学Golang
文章目录
- 非零基础自学Golang
- 第12章 接口与类型
- 12.2 接口的创建与实现
- 12.2.1 接口创建
第12章 接口与类型
12.2 接口的创建与实现
Go语言接口是方法的集合,使用接口是实现模块化的重要方式。
下面将重点介绍如何创建和实现一个Go语言接口。
12.2.1 接口创建
接口是用来定义行为类型的。
这些被定义的行为不由接口直接实现,而是由用户自定义的类型实现,一个实现了这些方法的具体类型就叫作这个接口类型的实例。
上一节也简单介绍了接口的定义,使用type和interface关键字即可创建一个接口。
接口内部只需要声明存在什么方法,不需要实现这些方法。
type InterfaceName interface{
Method()
}
比如,我们创建一个数据库操作的接口:
[ 动手写 12.2.1]
package main
type IDatabaser interface {
Connect() error
Disconnect() error
}
动手写12.2.1创建了一个叫IDatabaser的接口,这个接口声明了两个方法——Connect()和Disconnect(),只要哪个类型实现了这两个方法,就可以说该类型是IDatabaser接口的实例。
[ 动手写 12.2.2]
package main
import (
"errors"
"fmt"
)
// MySQL数据库
type Mysql struct {
DBName string
isConnect bool
}
func (mysql *Mysql) Connect() error {
fmt.Println("Mysql Connect DB => " + mysql.DBName)
// do Connect
mysql.isConnect = true
if mysql.isConnect {
fmt.Println("Mysql Connect Success!")
return nil
} else {
return errors.New("Connect failure!")
}
}
func (mysql *Mysql) Disconnect() error {
// do Disconnect
fmt.Println("Mysql Disconnect Success!")
return nil
}
动手写12.2.2创建了一个对MySQL数据库操作的类型,这个类型实现了IDatabaser接口中的两个方法,因此Mysql类型就是IDatabaser的一个实例。
我们再来创建一个对Redis数据库操作的类型:
package main
import "fmt"
// 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
}
这时候,我们就可以直接使用Mysql和Redis这两个类型来完成数据库操作:
[ 动手写12.2.4]
package main
import (
"errors"
"fmt"
)
type IDatabaser interface {
Connect() error
Disconnect() error
}
// MySQL数据库
type Mysql struct {
DBName string
isConnect bool
}
func (mysql *Mysql) Connect() error {
fmt.Println("Mysql Connect DB => " + mysql.DBName)
// do Connect
mysql.isConnect = true
if mysql.isConnect {
fmt.Println("Mysql Connect Success!")
return nil
} else {
return errors.New("Connect failure!")
}
}
func (mysql *Mysql) Disconnect() error {
// do Disconnect
fmt.Println("Mysql Disconnect Success!")
return nil
}
// 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 mysql = Mysql{DBName: "student"}
fmt.Println("开始连接")
mysql.Connect()
// do something
fmt.Println("断开连接")
mysql.Disconnect()
var redis = Redis{DBName: "teacher"}
fmt.Println("开始连接")
redis.Connect()
// do something
fmt.Println("断开连接")
redis.Disconnect()
}
运行结果
可以看到,我们虽然定义了接口,但是没有面向接口编程,所以动手写12.2.4会有很多重复的代码。
数据库类型越多,重复的代码也会越多,当我们面向接口编程时,就可以抽象出更简洁、更易于管理的代码,例如动手写12.2.5。
package main
import (
"errors"
"fmt"
)
type IDatabaser interface {
Connect() error
Disconnect() error
}
// Mysql数据库操作
type Mysql struct {
DBName string
isConnect bool
}
func (mysql *Mysql) Connect() error {
fmt.Println("Mysql Connect DB => " + mysql.DBName)
//do Connect
mysql.isConnect = true
if mysql.isConnect {
fmt.Println("Mysql Connect Success!")
return nil
} else {
return errors.New("Connect failure! ")
}
}
func (mysql *Mysql) Disconnect() error {
//do Disconnect
fmt.Println("Mysql Disconnect Success!")
return nil
}
// 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 HandleDB(db IDatabaser) {
fmt.Println("开始连接")
db.Connect()
//do something
fmt.Println("断开连接")
db.Disconnect()
}
func main() {
var mysql = Mysql{DBName: "student"}
HandleDB(&mysql)
var redis = Redis{DBName: "teacher"}
HandleDB(&redis)
}
运行结果
动手写12.2.5中,HandleDB()函数只有一个,却能实现处理多个不同类型的数据,这也称为Go的多态。
【提示】
Go语言中,一个类型可以实现多个接口,反之,多个类型也可以实现同一个接口,任何一个类型都必然实现了空接口。