Go 在不同型別之間需要明確的轉換。
型別之間的轉換(也稱為型別轉型)是透過以目標型別為名的函式來完成。
舉例來說,要把 int 轉換成 float64,你需要這樣做:
var x int = 42 // x has type int
f := float64(x) // f has type float64 (ie. 42.0)
有一個 strconv 套件可以在基本型別(例如 int)與 string 之間轉換。
import "strconv"
var intString string = "42"
var i, err = strconv.Atoi(intString)
var number int = 12
var s string = strconv.Itoa(number)
Go 中的介面可能會讓底層型別變得不明確。
型別斷言讓我們可以用以下語法,取出介面值底層的具體值:interfaceVariable.(concreteType)。
例如:
var input any = 12
number := input.(int)
注意:如果介面變數沒有持有具體型別的值,就會導致 panic。
我們可以利用型別斷言的兩個回傳值,來測試介面值是否持有某個特定的具體型別:底層的值,以及一個回報斷言是否成功的布林值。 例如:
str, ok := input.(string) // no panic if input is not a string
如果 input 持有 string,那麼 str 會是底層的值,而 ok 會是 true。
如果 input 沒有持有 string,那麼 str 會是 string 型別的零值(也就是 "",空字串),而 ok 會是 false。
無論哪種情況都不會發生 panic。
型別切換可以連續執行多個型別斷言。
它的語法和型別斷言(interfaceVariable.(concreteType))相同,只是把 concreteType 換成關鍵字 type。
以下是一個例子:
var i any = 12 // try: 12.3, true, int64(12), []int{}, map[string]int{}
switch v := i.(type) {
case int:
fmt.Printf("the integer %d\n", v)
case string:
fmt.Printf("the string %s\n", v)
default:
fmt.Printf("type, %T, not handled explicitly: %#v\n", v, v)
}
Jen 在一間大工廠的分揀室工作。 分揀室需要處理送進來的一切物品,方式是為它們貼上標籤分類。 Jen 負責的是那些事先被歸類為數字的東西,她需要一個程式來協助她分揀。
大多數基本型別的值都應該拿到簡單直接的標籤。
對於數字,她想要像"This is the number 2.0"這樣的字串(如果那個數字是 2)。
不論是整數還是浮點數,Jen 都想要同樣的輸出。
有幾個Box介面需要拆開才能取出裡面的內容。
對於NumberBox,她想要像"This is a box containing the number 3.0"這樣的字串(如果Number()方法回傳 3)。
對於FancyNumberBox,她想要像"This is a fancy box containing the number 4.0"這樣的字串,但只有在型別是FancyNumber的時候。
任何意料之外的東西都應該回傳"Return to sender",這樣 Jen 就能把它們送回原來的地方。
Jen 想要數字回傳像"This is the number 2.0"這樣的字串(包含小數點後一位):
fmt.Println(DescribeNumber(-12.345))
// Output: This is the number -12.3
Jen 想要數字盒回傳像"This is a box containing the number 2.0"這樣的字串(同樣包含小數點後一位):
fmt.Println(DescribeNumberBox(numberBoxContaining{12}))
// Output: This is a box containing the number 12.0
Jen 需要一個輔助函式,從FancyNumberBox取出數字。
如果FancyNumberBox是FancyNumber,就取出它的值,並把它從string轉換成int。
其他任何型別的FancyNumberBox都應該回傳 0。
fmt.Println(ExtractFancyNumber(FancyNumber{"10"}))
// Output: 10
fmt.Println(ExtractFancyNumber(AnotherFancyNumber{"4"}))
// Output: 0
如果FancyNumberBox是FancyNumber,Jen 想要像"This is a fancy box containing the number 4.0"這樣的字串。
其他任何型別的FancyNumberBox都應該回傳"This is a fancy box containing the number 0.0"。
fmt.Println(DescribeFancyNumberBox(FancyNumber{"10"}))
// Output: This is a fancy box containing the number 10.0
fmt.Println(DescribeFancyNumberBox(AnotherFancyNumber{"4"}))
// Output: This is a fancy box containing the number 0.0
注意:我們應該使用ExtractFancyNumber函式!
DescribeAnything,它會用到上述全部功能這是 Jen 需要的主要函式,它可以接受任何輸入。
DescribeAnything應該根據傳入值的型別,把工作委派給其他函式。
更精確地說:
int和float64都應該委派給DescribeNumber
NumberBox應該委派給DescribeNumberBox
FancyNumberBox應該委派給DescribeFancyNumberBox
"Return to sender"
fmt.Println(DescribeAnything(numberBoxContaining{12.345}))
// Output: This is a box containing the number 12.3
fmt.Println(DescribeAnything("some string"))
// Output: Return to sender