1、介紹
? ? ? ? Golang 語言是一門靜態類型的編程語言,我們在編寫代碼時,為了提升代碼的靈活性,有時會使用空接口類型,對于空接口類型的變量,一般會通過類型斷言判斷變量的類型,而且可能還會遇到遇到類型轉換的場景,下面我們對類型的斷言、類型轉換和類型選擇。
2、編程技巧
? ? ? ? 類型斷言,類型端要提供了訪問接口類型值的底層具體值的方式,這是需要注意的是被類型斷言的值必須是接口類型的值,類型斷言返回兩個值,被斷言的接口類型值的底層具體值和一個表示是否斷言成功的布爾類型的值。
t,ok := i.(T)
? ? ? ? 未使用類型斷言:
func main() {id := getVal(1)fmt.Println(id)
}func getVal(val interface{}) interface{} {return val
}
? ? ? ? 使用類型斷言:
func main() {id := getVal(1)id, ok := id.(int);if !ok {err := errors.New("illegal paramter")fmt.Println(err)return}fmt.Println(id)
}func getVal(val interface{}) interface{} {return val
}
? ? ? ? 閱讀上面這兩段代碼,main 函數中都是通過調用getVal()函數,使用類型推斷的方式給變量id 賦值,不同的是main 函數,第一段代碼中未使用類型斷言,第二段代碼中使用了類型斷言,所以第一代碼的main 函數如果調用 getVa()函數時傳遞非整型參數,也可以正常輸出;第二段代碼的main 函數如果調用 getVal() 函數時傳遞非整型參數,將會被斷言代碼攔截。
? ? ? ?類型轉換:
? ? ? ? 類型轉換的表達式T(v),將v 轉換為類型T 。關于類型轉換,我們需要注意的“坑”如下所示:
? ? ? ? 整型之間的轉換:
func main() {var a inta = 128b := int8(a)fmt.Println(b)
}
? ? ? ?輸出結果:-128
? ? ? ? 閱讀上面這段代碼, int 類型的變量 a 賦值為128 ,將變量a 轉換為int8 類型的變量b , 輸出變量b 的結果是 -128 ,原因是int 類型和 int8 類型的取值范圍不同。
? ? ? ? 浮點型轉為整形:
import "fmt"func main() {var a float64a = 3.1415926b := int(a)fmt.Println(b)
}
? ? ? ? 輸出結果:3
? ? ? ? 浮點型float64的變量a, 轉換為int 類型的變量b ,輸出結果是3,變量a 值的小數部分被截掉了。
????????整型轉換為字符串類型:
import "fmt"func main() {var a inta = -1b := string(a)fmt.Println(b)
}
? ? ? ? 輸出結果:�
????????int 類型變量 a,轉換為 string 類型變量 b,變量 b 的輸出結果是?�
,表示未知字符,原因是 Unicode 碼點(code point)中沒有 -1。
? ? ? ? 字符串類型和切片(字節切片和字符切片)類型相互轉換:
import "fmt"func main() {var a stringa = "編程"b := []byte(a)fmt.Println(b)c := []rune(a)fmt.Println(c)
}
? ? ? ?輸出結果:
????????[231 188 150 231 168 139]
[32534 31243]
? ? ? ? 將字符串類型的變量a 分別轉換為字節切片類型變量b 和字符切片類型變量c,它們的輸出結果不同,原因是UTF-8 編碼一個中文漢字是3個字節,3個字節代表1個字符 。而字符切片類型的元素本身就是Unicode 字符。
????????類型選擇:
func main() {var a interface{}a = falseswitch val := a.(type) {case int:fmt.Printf("val:%d type:%T\n", val, val)case string:fmt.Printf("val:%d type:%T\n", val, val)default:fmt.Printf("unknowtype:%T\n", val)}
}
? ? ? ? 這段代碼使用的 type swtich 判斷空接口類型變量a 的實際數據類型是否為我們預定義的類型之一。