Go 語言中,接口是一種強大的抽象機制。其中,空接口(
interface{}
)和類型斷言為我們提供了處理任意類型與類型檢查的能力。
一、空接口(interface{}
)
空接口是 Go 中最特殊的接口:不包含任何方法。因此,所有類型都實現了空接口。
定義:
var?a?interface{}
可以賦值為任意類型:
a?=?123
a?=?"hello"
a?=?[]int{1,?2,?3}
應用場景:
- ? 接收任意參數(如?
fmt.Println()
) - ? 構建通用數據結構(如?
map[string]interface{}
) - ? 動態處理數據(如?
json.Unmarshal
)
示例:通用打印函數
func?PrintAny(v?interface{})?{fmt.Println(v)
}
二、類型斷言(Type Assertion)
類型斷言用于將接口變量還原為具體類型。
基本語法:
value?:=?i.(T)????????//?斷言?i?為類型?T,失敗會?panic
value,?ok?:=?i.(T)????//?帶?ok?的寫法,斷言失敗不會?panic
示例:
var?i?interface{}?=?"hello"s?:=?i.(string)?????????//?正確
fmt.Println(s)??????????//?hellon,?ok?:=?i.(int)????????//?錯誤,但不會?panic
fmt.Println(ok)?????????//?false
? 建議優先使用帶?
ok
?的寫法,避免程序在斷言失敗時 panic。
三、配合?switch
?使用:類型判斷
使用?type switch
?可以根據接口中存儲的實際類型執行不同邏輯:
func?TypeCheck(x?interface{})?{switch?v?:=?x.(type)?{case?int:fmt.Println("int:",?v)case?string:fmt.Println("string:",?v)case?bool:fmt.Println("bool:",?v)default:fmt.Println("unknown?type")}
}
調用:
TypeCheck(42)?????????//?int:?42
TypeCheck("go")???????//?string:?go
TypeCheck(true)???????//?bool:?true
四、空接口 + JSON
Go 中 JSON 的解析常用?map[string]interface{}
:
var?data?=?`{"name":?"Tom",?"age":?30}`
var?result?map[string]interface{}
json.Unmarshal([]byte(data),?&result)fmt.Println(result["name"])?//?Tom
fmt.Println(result["age"])??//?30
此時?result["age"]
?實際類型是?float64
,需要進一步斷言:
if?age,?ok?:=?result["age"].(float64);?ok?{fmt.Println("Age?is",?int(age))
}
五、空接口的注意事項
- 1.?濫用空接口會降低類型安全性與可讀性,應在確實需要處理任意類型時使用;
- 2. 接口變量底層由兩部分組成:動態類型 + 動態值;
- 3. 空接口變量為 nil,必須?兩部分都為 nil?才等于 nil;
var?x?interface{}?=?nil???????????//?true var?p?*int?=?nil var?y?interface{}?=?p?????????????//?false(類型為?*int,不是?nil) fmt.Println(x?==?nil)?????????????//?true fmt.Println(y?==?nil)?????????????//?false
六、小結
概念 | 描述 |
空接口 | interface{} ,可存儲任意類型 |
類型斷言 | 將接口還原為具體類型 |
類型判斷 | 使用?switch v := x.(type) ?區分類型 |
JSON 場景 | 使用?map[string]interface{} ?處理動態結構 |
建議 | 斷言時使用?ok ?檢查,避免直接 panic |