9.1 Go Interface 基础知识学习笔记

Go Interface 基础知识学习笔记

1. 接口的定义

接口是一组方法签名的集合,定义了"行为"但不实现:

go 复制代码
type Shape interface {
    Area() float64
}

type Writer interface {
    Write([]byte) (int, error)
}

要点

  • 接口只声明方法签名,没有实现代码
  • 任何类型只要实现了接口的所有方法,就自动满足该接口,不需要显式声明
  • 这叫做隐式实现 (duck typing),Go 不像 Java 需要 implements 关键字

2. 实现接口

Rectangle 和 Circle 都实现了 Area() float64 方法,因此它们都自动满足 Shape 接口:

go 复制代码
type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

同样,Writer 接口定义如下:

go 复制代码
type Writer interface {
    Write([]byte) (int, error)
}

FileWriter 和 ConsoleWriter 都实现了 Write([]byte) (int, error) 方法,自动满足 Writer 接口:

go 复制代码
type FileWriter struct {
    Filename string
}

func (fw FileWriter) Write(data []byte) (int, error) {
    fmt.Printf("Writing %d bytes to file: %s\n", len(data), fw.Filename)
    fmt.Printf("Content: %s\n", string(data))
    return len(data), nil
}

type ConsoleWriter struct{}

func (cw ConsoleWriter) Write(data []byte) (int, error) {
    fmt.Printf("Console: %s", string(data))
    return len(data), nil
}

要点 :没有 implementsextends 等关键字。只要方法签名完全匹配(方法名、参数类型、返回值类型),就自动实现接口。


3. 接口作为函数参数 --- 多态

函数接收接口类型参数时,可以传入任何实现了该接口的类型:

go 复制代码
func printShapeInfo(s Shape) {
    fmt.Printf("Shape area: %.2f\n", s.Area())
}

func writeMessage(w Writer, message string) {
    w.Write([]byte(message))
}

不同类型传入同一个函数,表现出不同行为(多态):

go 复制代码
rect := Rectangle{Width: 5, Height: 3}
circle := Circle{Radius: 4}

printShapeInfo(rect)    // 输出: Shape area: 15.00
printShapeInfo(circle)  // 输出: Shape area: 50.27

fileWriter := FileWriter{Filename: "output.txt"}
consoleWriter := ConsoleWriter{}

writeMessage(fileWriter, "Hello, File!")
// 输出: Writing 12 bytes to file: output.txt
//       Content: Hello, File!

writeMessage(consoleWriter, "Hello, Console!")
// 输出: Console: Hello, Console!

要点 :函数不在乎传入的具体类型,只在乎它是否实现了接口要求的方法。这就是多态------同一接口,不同实现,不同行为。


4. 接口切片 --- 存储不同类型

接口类型的切片可以存储所有实现了该接口的不同类型:

go 复制代码
shapes := []Shape{rect, circle}

var totalArea float64
for _, shape := range shapes {
    totalArea += shape.Area()
}
fmt.Printf("Total area of all shapes: %.2f\n", totalArea)
// 输出: Total area of all shapes: 65.27

writers := []Writer{fileWriter, consoleWriter}

for i, writer := range writers {
    message := fmt.Sprintf("Message %d from writer\n", i+1)
    writeMessage(writer, message)
}
// 输出: Writing 22 bytes to file: output.txt / Content: Message 1 from writer
//       Console: Message 2 from writer

要点[]Shape 可以同时存放 Rectangle 和 Circle,[]Writer 可以同时存放 FileWriter 和 ConsoleWriter。这在没有接口的语言中是无法实现的(数组/切片要求所有元素类型相同)。


5. 接口赋值

接口变量可以动态切换底层类型:

go 复制代码
var shape Shape

shape = rect    // Rectangle 实现了 Shape
fmt.Printf("Shape (Rectangle) area: %.2f\n", shape.Area())  // 15.00

shape = circle  // Circle 也实现了 Shape
fmt.Printf("Shape (Circle) area: %.2f\n", shape.Area())     // 50.27

要点:接口变量内部存储了两部分信息:

  1. 类型信息 --- 底层是什么类型(Rectangle 还是 Circle)
  2. 值信息 --- 底层类型的实际数据

同一个 shape 变量可以先后指向不同类型的值,调用 shape.Area() 时,Go 根据 shape 当前的底层类型选择对应的方法实现。


知识点总结

知识点 关键概念
接口定义 type Name interface { 方法签名 },只声明不实现
隐式实现 不需要 implements,方法签名匹配即自动实现接口
多态 函数接收接口参数,不同类型表现出不同行为
接口切片 []Shape 可存放不同类型,统一遍历调用
接口赋值 同一个接口变量可动态切换底层类型
接口内部 存储 (类型, 值) 两部分信息,调用时根据类型选择方法
相关推荐
a187927218311 小时前
【算法】回溯算法(一):从一道 IP 题到万能模板
算法·leetcode·go·回溯·leetcode93·ip复原·算法讲解
名字还没想好☜2 小时前
Go 用 -race 抓数据竞争:一个偶发崩溃的排查、原理与修复
开发语言·后端·golang·go
Vespeng16 小时前
打破传统 MVC:在 Go 中实践高内聚的业务驱动架构
架构·go·gin
用户0296697698220 小时前
摸着石头过河:我用Go把微信加密模块给逆向了一回
微信·go
idcu1 天前
CodeSchema 开源首发:一个给 AI 编码助手「喂」精准代码上下文的索引服务
开源·go·ai编程
newerp2 天前
Golang 切片扩容策略
后端·程序员·go
我的div丢了肿么办2 天前
go中make声明切片, 修改切片,append给切片扩容,合并切片,复制切片
后端·go
纪卓志George2 天前
保守十四年:Go 的泛型方法与丢失的定位
go
运维开发笔记2 天前
8.3 Go Struct 嵌入学习笔记
go