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 风格。