类型断言

类型断言用于从接口值中提取具体的类型。本章将详细介绍类型断言的使用方法。

什么是类型断言?

类型断言是检查接口值是否包含特定类型的操作。

类型断言示意:

接口值 (type, value)
        ↓
    类型断言
        ↓
   具体类型值

基本语法

值 := 接口.(类型)
值, ok := 接口.(类型)

基本类型断言

不安全断言

package main

import "fmt"

func main() {
    var i interface{} = "hello"

    s := i.(string)
    fmt.Printf("字符串: %s\n", s)

    n := i.(int)
    fmt.Println(n)
}

直接断言失败会 panic,不推荐使用。

安全断言

package main

import "fmt"

func main() {
    var i interface{} = "hello"

    s, ok := i.(string)
    if ok {
        fmt.Printf("字符串: %s\n", s)
    } else {
        fmt.Println("不是字符串")
    }

    n, ok := i.(int)
    if ok {
        fmt.Printf("整数: %d\n", n)
    } else {
        fmt.Println("不是整数")
    }
}

类型切换

使用 switch 语句检查多种类型:

package main

import "fmt"

func TypeCheck(v interface{}) {
    switch t := v.(type) {
    case int:
        fmt.Printf("整数: %d\n", t)
    case string:
        fmt.Printf("字符串: %s\n", t)
    case bool:
        fmt.Printf("布尔: %t\n", t)
    case float64:
        fmt.Printf("浮点数: %f\n", t)
    case []int:
        fmt.Printf("整数切片: %v\n", t)
    case map[string]int:
        fmt.Printf("Map: %v\n", t)
    default:
        fmt.Printf("未知类型: %T\n", t)
    }
}

func main() {
    TypeCheck(42)
    TypeCheck("hello")
    TypeCheck(true)
    TypeCheck(3.14)
    TypeCheck([]int{1, 2, 3})
    TypeCheck(map[string]int{"a": 1})
    TypeCheck(struct{}{})
}

断言自定义类型

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var i interface{} = Person{Name: "张三", Age: 25}

    p, ok := i.(Person)
    if ok {
        fmt.Printf("姓名: %s, 年龄: %d\n", p.Name, p.Age)
    }
}

断言指针类型

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    var i interface{} = &Person{Name: "张三", Age: 25}

    p, ok := i.(*Person)
    if ok {
        fmt.Printf("姓名: %s, 年龄: %d\n", p.Name, p.Age)
    }

    p2, ok := i.(Person)
    fmt.Printf("值类型断言: %v\n", ok)
}

断言接口类型

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(s string) {
    f.content = s
}

func main() {
    var rw ReadWriter = &File{}

    r, ok := rw.(Reader)
    fmt.Printf("是 Reader: %v\n", ok)
    fmt.Println(r.Read())

    w, ok := rw.(Writer)
    fmt.Printf("是 Writer: %v\n", ok)
    w.Write("hello")
}

实际应用

处理 JSON 数据

package main

import (
    "encoding/json"
    "fmt"
)

func ParseJSON(data []byte) {
    var result interface{}
    json.Unmarshal(data, &result)

    switch v := result.(type) {
    case map[string]interface{}:
        fmt.Println("JSON 对象:")
        for key, val := range v {
            fmt.Printf("  %s: %v\n", key, val)
        }
    case []interface{}:
        fmt.Println("JSON 数组:")
        for i, val := range v {
            fmt.Printf("  [%d]: %v\n", i, val)
        }
    default:
        fmt.Printf("其他类型: %T\n", v)
    }
}

func main() {
    obj := `{"name": "张三", "age": 25}`
    ParseJSON([]byte(obj))

    arr := `[1, 2, 3, "four", true]`
    ParseJSON([]byte(arr))
}

错误类型判断

package main

import (
    "fmt"
    "os"
)

func main() {
    _, err := os.Open("nonexistent.txt")
    if err != nil {
        switch e := err.(type) {
        case *os.PathError:
            fmt.Printf("路径错误: %s\n", e.Path)
        case *os.LinkError:
            fmt.Printf("链接错误: %s -> %s\n", e.Old, e.New)
        default:
            fmt.Printf("其他错误: %v\n", e)
        }
    }
}

通用处理函数

package main

import "fmt"

func Process(v interface{}) {
    switch t := v.(type) {
    case int:
        fmt.Printf("整数翻倍: %d\n", t*2)
    case string:
        fmt.Printf("字符串长度: %d\n", len(t))
    case []int:
        sum := 0
        for _, n := range t {
            sum += n
        }
        fmt.Printf("切片求和: %d\n", sum)
    default:
        fmt.Printf("不支持的类型: %T\n", t)
    }
}

func main() {
    Process(10)
    Process("hello")
    Process([]int{1, 2, 3, 4, 5})
    Process(3.14)
}

总结

本章学习了 Go 语言的类型断言:

知识点说明
基本断言v.(Type)
安全断言v, ok := i.(Type)
类型切换switch v := i.(type)
接口断言断言接口类型