第五章:接口与多态

作者:Administrator 发布时间: 2026-03-13 阅读量:1 评论数:0

第五章:接口与多态

5.1 接口基础

什么是接口

接口是一组方法签名的集合,定义了对象的行为。

package main
​
import "fmt"
​
// 定义接口
type Speaker interface {
    Speak() string
}
​
type Mover interface {
    Move() string
}
​
// 实现接口的类型
type Dog struct {
    Name string
}
​
func (d Dog) Speak() string {
    return "汪汪!"
}
​
func (d Dog) Move() string {
    return "四条腿跑"
}
​
type Cat struct {
    Name string
}
​
func (c Cat) Speak() string {
    return "喵喵~"
}
​
func (c Cat) Move() string {
    return "悄无声息地走"
}
​
// 多态函数
func MakeSpeak(s Speaker) {
    fmt.Println(s.Speak())
}
​
func main() {
    dog := Dog{Name: "旺财"}
    cat := Cat{Name: "咪咪"}
    
    // 多态调用
    MakeSpeak(dog)  // 汪汪!
    MakeSpeak(cat)  // 喵喵~
    
    // 接口变量
    var s Speaker
    s = dog
    fmt.Println(s.Speak())
    
    s = cat
    fmt.Println(s.Speak())
}

5.2 空接口

package main
​
import "fmt"
​
// 空接口可以接收任何类型
func printAny(v interface{}) {
    fmt.Printf("值: %v, 类型: %T\n", v, v)
}
​
// 类型断言
func process(v interface{}) {
    // 方式1:直接断言
    if str, ok := v.(string); ok {
        fmt.Println("是字符串:", str)
        return
    }
    
    // 方式2:switch类型判断
    switch val := v.(type) {
    case int:
        fmt.Println("是整数:", val)
    case float64:
        fmt.Println("是浮点数:", val)
    case bool:
        fmt.Println("是布尔值:", val)
    case []int:
        fmt.Println("是整数切片:", val)
    default:
        fmt.Println("未知类型:", val)
    }
}
​
func main() {
    printAny("hello")
    printAny(123)
    printAny(3.14)
    printAny(true)
    printAny([]int{1, 2, 3})
    
    fmt.Println("---")
    process("test")
    process(100)
    process(3.14)
    process([]int{1, 2, 3})
}

5.3 接口组合

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(data string) {
    f.Content = data
}
​
func main() {
    file := &File{}
    
    // 可以作为ReadWriter使用
    var rw ReadWriter = file
    rw.Write("Hello, World!")
    fmt.Println(rw.Read())
    
    // 也可以单独作为Reader或Writer
    var r Reader = file
    var w Writer = file
    
    fmt.Println(r.Read())
    w.Write("New content")
}

5.4 接口值与nil

package main
​
import "fmt"
​
type Person struct {
    Name string
}
​
func (p *Person) Speak() string {
    if p == nil {
        return "我是nil"
    }
    return "我叫" + p.Name
}
​
type Speaker interface {
    Speak() string
}
​
func main() {
    var p *Person  // nil指针
    
    // 接口值不是nil,但内部指针是nil
    var s Speaker = p
    fmt.Println(s != nil)  // true
    fmt.Println(s.Speak()) // 我是nil
    
    // 真正的nil接口
    var s2 Speaker
    fmt.Println(s2 == nil)  // true
    // s2.Speak()  // panic!
}

5.5 常用标准库接口

package main
​
import (
    "bytes"
    "fmt"
    "io"
    "os"
    "strings"
)
​
func main() {
    // fmt.Stringer接口
    type Person struct {
        Name string
        Age  int
    }
    
    // io.Reader/io.Writer
    var buf bytes.Buffer
    buf.WriteString("Hello, ")
    buf.WriteString("World!")
    fmt.Println(buf.String())
    
    // 标准输入输出
    // io.Copy(os.Stdout, os.Stdin)
    
    // strings.Reader
    r := strings.NewReader("Hello")
    data := make([]byte, 5)
    r.Read(data)
    fmt.Println(string(data))
    
    // error接口
    err := fmt.Errorf("错误信息: %s", "出错了")
    fmt.Println(err)
}

5.6 项目实战:形状计算

package main
​
import (
    "fmt"
    "math"
)
​
// 形状接口
type Shape interface {
    Area() float64
    Perimeter() float64
}
​
// 圆形
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
}
​
// 矩形
type Rectangle struct {
    Width, Height float64
}
​
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}
​
func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}
​
// 三角形
type Triangle struct {
    A, B, C float64  // 三边
}
​
func (t Triangle) Area() float64 {
    // 海伦公式
    s := t.Perimeter() / 2
    return math.Sqrt(s * (s - t.A) * (s - t.B) * (s - t.C))
}
​
func (t Triangle) Perimeter() float64 {
    return t.A + t.B + t.C
}
​
// 多态函数
func PrintShapeInfo(s Shape) {
    fmt.Printf("面积: %.2f, 周长: %.2f\n", s.Area(), s.Perimeter())
}
​
// 计算总面积
func TotalArea(shapes []Shape) float64 {
    total := 0.0
    for _, s := range shapes {
        total += s.Area()
    }
    return total
}
​
func main() {
    shapes := []Shape{
        Circle{Radius: 5},
        Rectangle{Width: 10, Height: 5},
        Triangle{A: 3, B: 4, C: 5},
    }
    
    for _, s := range shapes {
        PrintShapeInfo(s)
    }
    
    fmt.Printf("总面积: %.2f\n", TotalArea(shapes))
}

评论