ZetCode

Golang any 类型

最后修改时间 2025 年 5 月 8 日

本教程解释了如何在 Go 中使用 any 内置类型。我们将通过灵活类型处理的实际示例来介绍类型基础知识。

any 类型是一个预声明的接口类型,表示所有非接口类型的集合。它是 Go 1.18 中引入的 interface{} 的别名,旨在提高代码的可读性。

在 Go 中,当你需要处理未知类型的变量时,可以使用 any。它提供了灵活性,但需要类型断言或类型开关来访问底层具体值。

基本的 any 类型示例

any 最简单的用法是存储不同类型的值。本示例演示了 any 类型的基本用法。
注意: any 可以持有任何类型的变量,类似于 C 中的 void*。

basic_any.go
package main

import "fmt"

func main() {

    var a any
    
    a = 42
    fmt.Printf("Type: %T, Value: %v\n", a, a)
    
    a = "hello"
    fmt.Printf("Type: %T, Value: %v\n", a, a)
    
    a = 3.14
    fmt.Printf("Type: %T, Value: %v\n", a, a)
}

变量 a 可以持有不同类型的值。%T 格式动词显示存储在 any 变量中的动态类型。

使用 any 进行类型断言

我们可以使用类型断言从 any 中提取具体值。本示例展示了如何安全地执行类型断言。

type_assertion.go
package main

import "fmt"

func main() {

    var val any = "gopher"
    
    // Safe type assertion with ok
    if s, ok := val.(string); ok {
        fmt.Println("It's a string:", s)
    } else {
        fmt.Println("Not a string")
    }
    
    val = 42
    if i, ok := val.(int); ok {
        fmt.Println("It's an int:", i)
    } else {
        fmt.Println("Not an int")
    }
}

ok 布尔值指示断言是否成功。这种模式可以防止因不正确的类型断言而导致的运行时恐慌。

使用 any 进行类型开关

类型开关提供了一种处理多种可能类型的简洁方法。本示例演示了如何将类型开关与 any 变量一起使用。

type_switch.go
package main

import "fmt"

func printType(v any) {
    switch t := v.(type) {
    case int:
        fmt.Println("Integer:", t)
    case float64:
        fmt.Println("Float:", t)
    case string:
        fmt.Println("String:", t)
    default:
        fmt.Printf("Unknown type: %T\n", t)
    }
}

func main() {

    printType(42)
    printType(3.14)
    printType("hello")
    printType(true)
}

类型开关会检查 any 变量的动态类型。每个 case 处理一种不同的可能类型,而 default 则捕获所有其他类型。

在函数参数中使用 any

对于需要接受多种类型的函数,any 非常有用。本示例展示了一个处理不同输入类型的函数。

function_param.go
package main

import "fmt"

func processValue(v any) {
    switch val := v.(type) {
    case int:
        fmt.Println("Processing integer:", val*2)
    case string:
        fmt.Println("Processing string:", len(val))
    case []int:
        fmt.Println("Processing slice:", len(val))
    default:
        fmt.Println("Unsupported type")
    }
}

func main() {

    processValue(10)
    processValue("golang")
    processValue([]int{1, 2, 3})
    processValue(3.14)
}

该函数分别处理整数、字符串和切片。不支持的类型将通过 default case。

Any 与 JSON 解码

Any 通常与结构未知的 JSON 数据一起使用。本示例展示了如何将 JSON 解析到 any 变量中。

json_unmarshal.go
package main

import (
    "encoding/json"
    "fmt"
)

func main() {

    jsonData := `{"name":"Alice","age":30,"active":true,"scores":[90,85,95]}`
    
    var data any
    err := json.Unmarshal([]byte(jsonData), &data)
    if err != nil {
        panic(err)
    }
    
    // Type assert to map[string]any
    if m, ok := data.(map[string]any); ok {
        fmt.Println("Name:", m["name"])
        fmt.Println("Age:", m["age"])
        
        if scores, ok := m["scores"].([]any); ok {
            fmt.Println("Scores:")
            for _, s := range scores {
                fmt.Println("-", s)
            }
        }
    }
}

将 JSON 解码到 any 会产生一个 map 和 slice 的层次结构。每一层都需要类型断言才能访问具体的值。

来源

Go 语言规范

本教程介绍了 Go 中的 any 类型,并提供了灵活处理类型和动态处理值的实际示例。

作者

我叫 Jan Bodnar,我是一名充满热情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面拥有十多年的经验。

列出所有 Golang 教程