空接口 #
一、空接口概述 #
空接口interface{}(Go 1.18+可写为any)不包含任何方法,因此所有类型都实现了空接口。
二、空接口定义 #
2.1 基本语法 #
go
var x interface{}
var y any // Go 1.18+
2.2 存储任意类型 #
go
var x interface{}
x = 42
fmt.Printf("%T: %v\n", x, x) // int: 42
x = "hello"
fmt.Printf("%T: %v\n", x, x) // string: hello
x = []int{1, 2, 3}
fmt.Printf("%T: %v\n", x, x) // []int: [1 2 3]
x = map[string]int{"a": 1}
fmt.Printf("%T: %v\n", x, x) // map[string]int: map[a:1]
2.3 函数参数 #
go
func Print(v interface{}) {
fmt.Println(v)
}
Print(42)
Print("hello")
Print([]int{1, 2, 3})
三、类型断言 #
3.1 基本语法 #
go
v, ok := x.(T)
3.2 示例 #
go
var x interface{} = "hello"
s, ok := x.(string)
if ok {
fmt.Println(s) // hello
}
n, ok := x.(int)
fmt.Println(ok) // false
3.3 不安全断言 #
go
var x interface{} = "hello"
s := x.(string) // 正确
fmt.Println(s)
n := x.(int) // panic: interface conversion
3.4 安全断言 #
go
func process(x interface{}) {
if s, ok := x.(string); ok {
fmt.Println("String:", s)
} else if n, ok := x.(int); ok {
fmt.Println("Int:", n)
} else {
fmt.Println("Unknown type")
}
}
四、类型switch #
4.1 基本语法 #
go
switch v := x.(type) {
case T:
// v是T类型
}
4.2 示例 #
go
func TypeOf(x interface{}) string {
switch v := x.(type) {
case int:
return fmt.Sprintf("int: %d", v)
case string:
return fmt.Sprintf("string: %s", v)
case bool:
return fmt.Sprintf("bool: %v", v)
case []int:
return fmt.Sprintf("[]int: %v", v)
default:
return fmt.Sprintf("unknown: %T", v)
}
}
4.3 多类型匹配 #
go
switch v := x.(type) {
case int, int32, int64:
fmt.Printf("Integer: %v\n", v)
case float32, float64:
fmt.Printf("Float: %v\n", v)
default:
fmt.Printf("Other: %T\n", v)
}
4.4 nil检查 #
go
func process(x interface{}) {
switch v := x.(type) {
case nil:
fmt.Println("nil")
case string:
fmt.Println("String:", v)
default:
fmt.Println("Other:", v)
}
}
五、实际应用 #
5.1 通用容器 #
go
type Container struct {
items []interface{}
}
func (c *Container) Add(item interface{}) {
c.items = append(c.items, item)
}
func (c *Container) Get(index int) interface{} {
return c.items[index]
}
c := Container{}
c.Add(42)
c.Add("hello")
c.Add([]int{1, 2, 3})
5.2 JSON处理 #
go
func parseJSON(data []byte) (interface{}, error) {
var result interface{}
err := json.Unmarshal(data, &result)
return result, err
}
func processJSON(data []byte) {
result, _ := parseJSON(data)
switch v := result.(type) {
case map[string]interface{}:
fmt.Println("Object:", v)
case []interface{}:
fmt.Println("Array:", v)
default:
fmt.Println("Other:", v)
}
}
5.3 函数参数 #
go
func Printf(format string, args ...interface{}) {
fmt.Printf(format, args...)
}
5.4 配置解析 #
go
type Config map[string]interface{}
func (c Config) GetString(key string) string {
if v, ok := c[key].(string); ok {
return v
}
return ""
}
func (c Config) GetInt(key string) int {
if v, ok := c[key].(int); ok {
return v
}
return 0
}
func (c Config) GetSlice(key string) []interface{} {
if v, ok := c[key].([]interface{}); ok {
return v
}
return nil
}
六、反射 #
6.1 基本用法 #
go
func inspect(x interface{}) {
t := reflect.TypeOf(x)
v := reflect.ValueOf(x)
fmt.Printf("Type: %v\n", t)
fmt.Printf("Value: %v\n", v)
fmt.Printf("Kind: %v\n", t.Kind())
}
6.2 类型判断 #
go
func isInt(x interface{}) bool {
return reflect.TypeOf(x).Kind() == reflect.Int
}
6.3 遍历结构体 #
go
func printFields(x interface{}) {
v := reflect.ValueOf(x)
t := v.Type()
for i := 0; i < v.NumField(); i++ {
field := t.Field(i)
value := v.Field(i)
fmt.Printf("%s: %v\n", field.Name, value)
}
}
七、空接口陷阱 #
7.1 类型丢失 #
go
func process(x interface{}) {
fmt.Printf("%T\n", x) // 类型信息保留
}
var s []int = []int{1, 2, 3}
process(s) // []int
7.2 nil处理 #
go
var x interface{}
fmt.Println(x == nil) // true
var s *string
x = s
fmt.Println(x == nil) // false(接口值不为nil)
7.3 比较 #
go
var x, y interface{}
x = []int{1, 2, 3}
y = []int{1, 2, 3}
fmt.Println(x == y) // panic: comparing uncomparable type []int
八、any类型 #
8.1 Go 1.18+ #
go
// any是interface{}的别名
type any = interface{}
var x any
x = 42
x = "hello"
8.2 泛型中的使用 #
go
func Print[T any](v T) {
fmt.Println(v)
}
九、最佳实践 #
9.1 避免滥用空接口 #
go
// 不好:过度使用空接口
func Process(data interface{}) interface{}
// 好:使用具体类型或接口
func Process(data []byte) error
9.2 使用类型断言 #
go
func process(x interface{}) {
if s, ok := x.(string); ok {
fmt.Println(s)
}
}
9.3 使用类型switch #
go
func process(x interface{}) {
switch v := x.(type) {
case int:
fmt.Println("int:", v)
case string:
fmt.Println("string:", v)
}
}
十、总结 #
空接口要点:
| 特性 | 说明 |
|---|---|
| 定义 | interface{} 或 any |
| 存储 | 可存储任意类型 |
| 断言 | x.(T) |
| 类型switch | switch x.(type) |
关键点:
- 任意类型:空接口可存储任意类型
- 类型断言:安全断言使用
v, ok := x.(T) - 类型switch:处理多种类型
- 反射:使用reflect包获取类型信息
- 避免滥用:优先使用具体类型或接口
准备好学习Goroutine了吗?让我们进入下一章!
最后更新:2026-03-26