Go 语言入门教程
空接口与 any
本教程共 80 篇 · 第 44 篇 · 更新于 2026-07-27 · 约 6 分钟阅读
GoGo 入门教程空接口anyinterface{}类型别名
44. 空接口与 any
本节目标:搞懂空接口是什么,学会用 any 替代 interface{},知道空接口的适用场景和陷阱。
空接口是什么
空接口就是没有任何方法的接口:
type Empty interface{}
因为空接口没有任何方法,所有类型都自动满足它。这意味着空接口变量能存任何类型的值:
package main
import "fmt"
func main() {
var v interface{}
v = 42
fmt.Println(v) // 42
v = "hello"
fmt.Println(v) // hello
v = []int{1, 2, 3}
fmt.Println(v) // [1 2 3]
v = struct{ Name string }{"Alice"}
fmt.Println(v) // {Alice}
}
any 是 interface{} 的别名
Go 1.18 引入了 any 关键字,它是 interface{} 的类型别名:
// Go 源码里的定义
type any = interface{}
两者完全等价,用哪个都行:
// 老写法
func Print(v interface{}) {
fmt.Println(v)
}
// 新写法(Go 1.18+)
func Print(v any) {
fmt.Println(v)
}
Tip从 Go 1.18 开始,推荐用
any替代interface{}。更短、更易读,官方文档和标准库已经全面切换到any。
空接口的用途
接收任意类型的参数
当函数需要接收任意类型的参数时,用 any:
func Println(v any) {
fmt.Println(v)
}
Println(42)
Println("hello")
Println(true)
标准库的 fmt.Println 就是用 any 接收参数的:
func Println(a ...any) (n int, err error)
存储任意类型的集合
// 混合类型的列表
list := []any{42, "hello", true, 3.14}
for _, v := range list {
fmt.Printf("%T: %v\n", v, v)
}
// int: 42
// string: hello
// bool: true
// float64: 3.14
map 存任意值
// key 和 value 都是任意类型
data := map[string]any{
"name": "Alice",
"age": 30,
"scores": []int{90, 85, 88},
}
JSON 解析时经常遇到这种结构,encoding/json 把未知结构的 JSON 解析成 map[string]any。
从空接口取值
空接口存了值之后,取出来用需要类型断言:
package main
import "fmt"
func main() {
var v any = "hello"
// 取值需要类型断言
s, ok := v.(string)
if ok {
fmt.Println(s) // hello
}
}
Warning不能直接对空接口变量做类型特定的操作。比如
v存的是 string,但你不能直接len(v),编译器不知道v是什么类型。必须先断言。
var v any = "hello"
// fmt.Println(len(v)) // 编译错误
fmt.Println(len(v.(string))) // 5 先断言再操作
空接口的陷阱
丢失类型安全
用 any 意味着编译器不再帮你检查类型,bug 要到运行时才暴露:
// 用 any,编译器不检查类型
func add(a, b any) any {
return a.(int) + b.(int) // 如果传的不是int就panic
}
add(1, 2) // 3
add(1, "hello") // panic!
比较的坑
空接口可以比较,但如果底层类型不可比较会 panic:
var a any = []int{1, 2}
var b any = []int{1, 2}
fmt.Println(a == b) // panic: runtime error: comparing uncomparable type []int
Note切片、map、函数这些不可比较的类型存到
any里后,用==比较会 panic。如果不确定底层类型,先做类型判断。
什么时候用 any
- 需要接收任意类型(如
fmt.Println) - 解析未知结构的 JSON
- 泛型无法覆盖的场景
什么时候不该用 any:
- 类型确定时用具体类型,不要图省事用 any
- 能用泛型解决的不要用 any(泛型有类型安全)
- 能用接口的不要用 any(接口有语义约束)
TipGo 1.18 以后,很多以前用空接口的场景可以用泛型替代。泛型既保留了通用性,又有编译期类型检查。后面泛型章节会详细讲。
小结
空接口和 any 的要点:
any是interface{}的别名(Go 1.18+),推荐用any- 空接口能存任何类型的值
- 取值需要类型断言
- 用空接口会丢失类型安全,能用泛型就用泛型
下一章讲接口的组合与嵌入。