接口是 Go 语言实现多态的核心机制。本章将详细介绍接口的定义和使用。
接口是一组方法的集合,它定义了对象的行为。任何实现了这些方法的类型,都自动实现了该接口。
接口示意:
┌─────────────────────────────────────┐
│ Shape 接口 │
├─────────────────────────────────────┤
│ Area() float64 │
│ Perimeter() float64 │
└─────────────────────────────────────┘
↑ ↑
│ │
┌────┴────┐ ┌────┴────┐
│ Rectangle│ │ Circle │
└─────────┘ └─────────┘
type 接口名 interface {
方法名1(参数) 返回值
方法名2(参数) 返回值
}
package main
import (
"fmt"
"math"
)
type Shape interface {
Area() float64
Perimeter() float64
}
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Width + r.Height)
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return math.Pi * c.Radius * c.Radius
}
func (c Circle) Perimeter() float64 {
return 2 * math.Pi * c.Radius
}
func main() {
var s Shape
s = Rectangle{Width: 10, Height: 5}
fmt.Printf("矩形面积: %.2f\n", s.Area())
s = Circle{Radius: 5}
fmt.Printf("圆形面积: %.2f\n", s.Area())
}
Go 的接口是隐式实现的,不需要显式声明 implements:
package main
import "fmt"
type Writer interface {
Write([]byte) (int, error)
}
type FileWriter struct{}
func (fw FileWriter) Write(data []byte) (int, error) {
fmt.Printf("写入文件: %s\n", string(data))
return len(data), nil
}
func main() {
var w Writer = FileWriter{}
w.Write([]byte("Hello"))
}
package main
import "fmt"
type Animal interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string {
return "汪汪汪"
}
type Cat struct{}
func (c Cat) Speak() string {
return "喵喵喵"
}
func MakeSound(a Animal) {
fmt.Println(a.Speak())
}
func main() {
dog := Dog{}
cat := Cat{}
MakeSound(dog)
MakeSound(cat)
}
输出:
汪汪汪
喵喵喵
空接口 interface{} 没有任何方法,所有类型都实现了空接口:
package main
import "fmt"
func PrintAny(v interface{}) {
fmt.Printf("值: %v, 类型: %T\n", v, v)
}
func main() {
PrintAny(42)
PrintAny("hello")
PrintAny(3.14)
PrintAny([]int{1, 2, 3})
}
package main
import "fmt"
func main() {
data := map[string]interface{}{
"name": "张三",
"age": 25,
"active": true,
"scores": []int{90, 85, 88},
}
fmt.Printf("data: %v\n", data)
}
package main
import "fmt"
func main() {
var i interface{} = "hello"
s := i.(string)
fmt.Println(s)
n := i.(int)
fmt.Println(n)
}
package main
import "fmt"
func main() {
var i interface{} = "hello"
s, ok := i.(string)
if ok {
fmt.Printf("字符串: %s\n", s)
}
n, ok := i.(int)
if ok {
fmt.Printf("整数: %d\n", n)
} else {
fmt.Println("不是整数")
}
}
package main
import "fmt"
func TypeCheck(v interface{}) {
switch t := v.(type) {
case int:
fmt.Printf("整数: %d\n", t)
case string:
fmt.Printf("字符串: %s\n", t)
case bool:
fmt.Printf("布尔: %t\n", t)
default:
fmt.Printf("未知类型: %T\n", t)
}
}
func main() {
TypeCheck(42)
TypeCheck("hello")
TypeCheck(true)
TypeCheck(3.14)
}
package main
import "fmt"
type Reader interface {
Read() string
}
type Writer interface {
Write(string)
}
type ReadWriter interface {
Reader
Writer
}
type File struct {
content string
}
func (f *File) Read() string {
return f.content
}
func (f *File) Write(s string) {
f.content = s
}
func main() {
var rw ReadWriter = &File{}
rw.Write("Hello, Go!")
fmt.Println(rw.Read())
}
package main
import "fmt"
type Speaker interface {
Speak()
}
type Mover interface {
Move()
}
type Animal interface {
Speaker
Mover
}
type Dog struct{}
func (d Dog) Speak() {
fmt.Println("汪汪汪")
}
func (d Dog) Move() {
fmt.Println("跑起来")
}
func main() {
var a Animal = Dog{}
a.Speak()
a.Move()
}
接口值由两部分组成:类型和值:
package main
import "fmt"
func main() {
var i interface{}
fmt.Printf("类型: %T, 值: %v, 是否为nil: %v\n", i, i, i == nil)
i = 42
fmt.Printf("类型: %T, 值: %v\n", i, i)
i = "hello"
fmt.Printf("类型: %T, 值: %v\n", i, i)
}
package main
import "fmt"
type Logger interface {
Log(message string)
}
type ConsoleLogger struct{}
func (cl ConsoleLogger) Log(message string) {
fmt.Printf("[Console] %s\n", message)
}
type FileLogger struct {
Filename string
}
func (fl FileLogger) Log(message string) {
fmt.Printf("[File: %s] %s\n", fl.Filename, message)
}
func Process(logger Logger, data string) {
logger.Log("开始处理: " + data)
logger.Log("处理完成")
}
func main() {
consoleLogger := ConsoleLogger{}
Process(consoleLogger, "数据1")
fileLogger := FileLogger{Filename: "app.log"}
Process(fileLogger, "数据2")
}
package main
import "fmt"
type PaymentMethod interface {
Pay(amount float64) string
}
type CreditCard struct {
Number string
}
func (cc CreditCard) Pay(amount float64) string {
return fmt.Sprintf("信用卡 %s 支付 %.2f 元", cc.Number, amount)
}
type Alipay struct {
Account string
}
func (a Alipay) Pay(amount float64) string {
return fmt.Sprintf("支付宝 %s 支付 %.2f 元", a.Account, amount)
}
type WechatPay struct {
OpenID string
}
func (w WechatPay) Pay(amount float64) string {
return fmt.Sprintf("微信 %s 支付 %.2f 元", w.OpenID, amount)
}
func Checkout(method PaymentMethod, amount float64) {
fmt.Println(method.Pay(amount))
}
func main() {
Checkout(CreditCard{Number: "****1234"}, 100.00)
Checkout(Alipay{Account: "user@example.com"}, 200.00)
Checkout(WechatPay{OpenID: "wx123"}, 300.00)
}
本章学习了 Go 语言的接口:
| 知识点 | 说明 |
|---|---|
| 定义 | type Name interface { ... } |
| 实现 | 隐式实现,无需声明 |
| 多态 | 同一接口不同实现 |
| 空接口 | interface{},可存储任意类型 |
| 类型断言 | v.(Type) 获取接口值的具体类型 |
| 接口组合 | 嵌套多个接口 |