Go类型断言
类型断言从接口值中提取具体类型的值,是接口使用的关键操作。
类型断言语法
基本语法
Go
var i interface{} = 42
// 断言类型
n := i.(int)
fmt.Println(n) // 42
// 断言失败panic
s := i.(string) // panic: interface conversion
类型断言检查接口实际类型是否匹配。
断言格式
Go
// 语法:接口值.(目标类型)
value := i.(Type)
// i必须是接口类型
// Type必须是具体类型或接口类型
安全类型断言
ok返回值
Go
var i interface{} = 42
// 安全断言
n, ok := i.(int)
if ok {
fmt.Println("是int:", n)
}
s, ok := i.(string)
if !ok {
fmt.Println("不是string")
}
使用ok形式避免panic,ok为bool表示是否成功。
常用模式
Go
func process(i interface{}) {
if n, ok := i.(int); ok {
fmt.Println("处理int:", n)
return
}
if s, ok := i.(string); ok {
fmt.Println("处理string:", s)
return
}
fmt.Println("未知类型")
}
断言接口类型
断言为另一接口
Go
type Reader interface {
Read(p []byte) (int, error)
}
type ReadWriter interface {
Reader
Write(p []byte) (int, error)
}
var rw ReadWriter = MyRW{}
// 断言为更小接口
var r Reader = rw // 直接赋值
// 或断言
r, ok := rw.(Reader) // ok=true
// 断言为更大接口(需类型实现)
rw2, ok := r.(ReadWriter) // ok取决于类型
接口断言示例
Go
func isReadWriter(i interface{}) bool {
rw, ok := i.(ReadWriter)
return ok
}
类型断言用途
检查类型
Go
func handle(i interface{}) {
switch {
case _, ok := i.(int); ok:
fmt.Println("int类型")
case _, ok := i.(string); ok:
fmt.Println("string类型")
default:
fmt.Println("其他类型")
}
}
获取具体值
Go
var i interface{} = User{Name: "Tom"}
// 获取User值
if u, ok := i.(User); ok {
fmt.Println(u.Name)
}
// 获取User指针
if u, ok := i.(*User); ok {
fmt.Println(u.Name)
}
调用特定方法
Go
type Stringer interface {
String() string
}
func printString(i interface{}) {
if s, ok := i.(Stringer); ok {
fmt.Println(s.String())
} else {
fmt.Println(i)
}
}
类型断言与类型转换对比
| 特性 | 类型断言 | 类型转换 |
|---|---|---|
| 用途 | 接口→具体类型 | 类型间转换 |
| 语法 | i.(T) | T(v) |
| 对象 | 接口值 | 具体类型值 |
| 检查 | 运行时检查 | 编译时检查 |
| 失败 | panic或ok=false | 编译错误 |
类型断言原理
内部检查
Go
// 类型断言检查:
// 1. 比较接口的_type.hash与目标类型hash
// 2. hash匹配则返回data指针
// 3. 不匹配则panic或ok=false
// 快速检查:hash比较(整数比较)
// 完整检查:类型结构比较(慢)
类型断言示例
Go
func processResponse(resp interface{}) error {
// 断言为特定类型
httpResp, ok := resp.(*http.Response)
if !ok {
return errors.New("不是HTTP响应")
}
// 使用具体类型
fmt.Println("状态码:", httpResp.StatusCode)
return nil
}
// 或使用type switch
func processResponse(resp interface{}) {
switch r := resp.(type) {
case *http.Response:
fmt.Println("HTTP:", r.StatusCode)
case string:
fmt.Println("字符串:", r)
default:
fmt.Println("其他")
}
}
类型断言常用场景
| 场景 | 用法 | 示例 |
|---|---|---|
| 类型检查 | 判断类型 | i.(int) |
| 获取值 | 提取具体值 | u, ok := i.(User) |
| 方法调用 | 调用特定方法 | s, ok := i.(Stringer) |
| 错误处理 | 检查错误类型 | e, ok := err.(MyError) |
| JSON处理 | 解析后判断 | m, ok := data.(map[string]interface{}) |
要点总结
- 类型断言:
i.(T)从接口获取具体类型值 - 断言失败panic,使用ok形式避免
- ok形式:
v, ok := i.(T) - 可断言为具体类型或接口类型
- 断言检查运行时实际类型
- 用于类型检查、获取值、调用方法
- type switch处理多种类型更简洁
- 断言效率高:hash快速比较
📝 发现内容有误?点击此处直接编辑