Go 接口(interface)

Go 接口(interface)


🧱 一、什么是 interface?

interface 是 Go 语言中实现 多态(polymorphism) 的核心机制。

一句话解释:接口就是一种行为的抽象它定义了一组方法,而不是具体的实现。任何类型只要实现了接口定义的方法,就被视为实现了该接口。


📐 二、interface 的基本语法

type Speaker interface {
    Speak()
}

上面这个接口定义了一个 Speak() 方法,任何类型只要有 Speak() 方法,就自动实现了 Speaker 接口。


✅ 示例一:简单实现

type LiuBei struct{}
type CaoCao struct{}
​
func (l LiuBei) Speak() {
    fmt.Println("我是刘备,仁德为本")
}
​
func (c CaoCao) Speak() {
    fmt.Println("宁教我负天下人,休教天下人负我")
}
​
func introduce(s Speaker) {
    s.Speak()
}

使用:

introduce(LiuBei{})   // 输出:我是刘备,仁德为本
introduce(CaoCao{})   // 输出:宁教我负天下人,休教天下人负我

🧠 三、interface 的本质(非常重要)

interface 是什么?

从底层看,interface 本质上是一个二元结构,包含:

  1. type:实际数据的类型

  2. value:实际数据的值

type iface struct {
    tab  *itab  // 类型信息
    data unsafe.Pointer // 实际数据
}

所以你传的是值,底层是“值 + 类型”,用的是动态分发。


📦 四、隐式实现 & 解耦设计

Go 语言的接口是隐式实现的,即:不需要显式声明“我实现了哪个接口”,只要方法签名对得上,就自动实现接口。

这一点在解耦方面非常强大,比如你可以轻松替换不同的模块。


🧰 五、接口类型变量

var s Speaker

这是一个接口变量,可以接收任何实现了 Speak() 方法的值。

s = LiuBei{}
s.Speak()  // 输出:我是刘备,仁德为本

🛠 六、空接口 interface{}

interface{}

空接口没有任何方法,所有类型都实现了它,所以可以表示任意值。

使用场景:

  • fmt.Println(...)

  • map[string]interface{}

  • json.Unmarshal 时的 interface{}

func show(v interface{}) {
    fmt.Println("值是:", v)
}

🧰 七、类型断言(Type Assertion)

把接口变量还原成它的具体类型:

var s Speaker = LiuBei{}
​
liu, ok := s.(LiuBei)
if ok {
    fmt.Println("转换成功:", liu)
}

也可用于空接口:

var x interface{} = "Hello"
​
str := x.(string)        // 安全:类型匹配
num := x.(int)           // 会 panic:类型不匹配

建议使用断言+判断:

if str, ok := x.(string); ok {
    fmt.Println("是字符串", str)
}

🧪 八、类型 switch

func testType(v interface{}) {
    switch value := v.(type) {
    case string:
        fmt.Println("字符串:", value)
    case int:
        fmt.Println("整数:", value)
    default:
        fmt.Println("未知类型")
    }
}

🔁 九、接口组合(组合多个行为)

type Reader interface {
    Read(p []byte) (n int, err error)
}
​
type Writer interface {
    Write(p []byte) (n int, err error)
}
​
type ReadWriter interface {
    Reader
    Writer
}

ReadWriter 就是组合了 Reader + Writer 两个接口,Go 中所有接口都可以像这样组合。


🎮 十、用三国人物设计一组接口

type Warrior interface {
    Attack()
}
​
type Strategist interface {
    Plan()
}
​
type Commander interface {
    Warrior
    Strategist
}

定义几个人物:

type GuanYu struct{}
func (g GuanYu) Attack() { fmt.Println("关羽奋勇杀敌") }
​
type ZhugeLiang struct{}
func (z ZhugeLiang) Plan() { fmt.Println("诸葛亮妙计安天下") }
​
type LiuBei struct{}
func (l LiuBei) Attack()  { fmt.Println("刘备激励士气") }
func (l LiuBei) Plan()    { fmt.Println("刘备善用人心") }

使用:

func LeadBattle(c Commander) {
    c.Plan()
    c.Attack()
}
​
LeadBattle(LiuBei{})

📏 十一、interface 使用建议

建议原因
尽量面向接口编程实现解耦,便于测试
接口要小而精Go 强调“小接口”
接口定义应由使用者定义不由实现者来决定(反转)
使用空接口时一定要断言类型保证类型安全
使用结构体嵌套组合接口更灵活、更可扩展

✅ 十二、总结

概念说明
interface行为抽象,不关心数据类型
隐式实现只要方法匹配就自动实现
空接口万能类型
类型断言从接口变量中取出原始值
接口组合将多个接口拼合为一体

👉 立即点击链接,开启你的全栈开发之路:Golang全栈开发完整课程

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值