Go 接口 interface

接口定义一组方法签名(只写名称和参数,不写实现)。Go 接口是隐式实现的:类型不需要写 "implements",方法齐全就自动算实现。(说明:文中的片段代码需放进完整程序里运行)

定义接口与隐式实现

完整示例:

package main

import "fmt"

type Shape interface { // 两个方法签名
	Area() float64
	Perimeter() float64
}

type Rect struct{ W, H float64 }

func (r Rect) Area() float64      { return r.W * r.H }
func (r Rect) Perimeter() float64 { return 2 * (r.W + r.H) }

type Circle struct{ R float64 }

func (c Circle) Area() float64      { return 3.14 * c.R * c.R }
func (c Circle) Perimeter() float64 { return 2 * 3.14 * c.R }

func show(s Shape) { // 参数写接口类型
	fmt.Printf("面积=%.2f 周长=%.2f\n", s.Area(), s.Perimeter())
}

func main() {
	show(Rect{W: 3, H: 4})
	show(Circle{R: 1})
}
// 输出:
// 面积=12.00 周长=14.00
// 面积=3.14 周长=6.28

Rect、Circle 都没写"实现 Shape",方法齐全即可传入 show——这就是面向接口编程。

空接口与类型断言

空接口 interface{} 没有任何方法,所有类型都实现它,可以装任意值(Go 1.18 起可用 any 代替)。取回具体类型用类型断言 值.(类型)

var v interface{} = 42
fmt.Println(v) // 42

n, ok := v.(int) // 断言:ok 表示是否成功
fmt.Println(n, ok) // 42 true

s, ok2 := v.(string) // 失败时 s 是零值 ""
fmt.Printf("s=%q ok=%v\n", s, ok2)
// x := v.(string) // 不判 ok 直接断言,失败会 panic

接口嵌套

接口可以嵌套接口,结果接口的方法集是两者的并集:

type Reader interface{ Read() }
type Writer interface{ Write() }

type ReadWriter interface {
	Reader
	Writer
}
// File 只要实现 Read()、Write() 就满足 ReadWriter

常见用法:fmt.Stringer 等

标准库到处是接口。最常遇到 fmt.Stringer:类型实现 String() string 后,用 fmt 打印它会自动调用:

type Student struct{ Name string }

func (s Student) String() string { return "学生:" + s.Name }

// fmt.Println(Student{Name: "小明"}) → 学生:小明

其他常用接口:error(错误值)、io.Reader / io.Writer(流读写)、sort.Interface(自定义排序)。

小结:接口 = 方法签名集合;隐式实现让代码松耦合,空接口加断言负责"任意类型",fmt.Stringer 这类小接口最能体现 Go 风格。

笔记加载中…