學習軌道
/
Go
Go
/
練習
/
分類室
分類室

分類室

學習練習

簡介

型別轉換

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 就能把它們送回原來的地方。

1. 描述簡單的數字

Jen 想要數字回傳像"This is the number 2.0"這樣的字串(包含小數點後一位):

fmt.Println(DescribeNumber(-12.345))
// Output: This is the number -12.3

2. 描述數字盒

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

3. 實作從花俏數字盒取出數字的方法

Jen 需要一個輔助函式,從FancyNumberBox取出數字。 如果FancyNumberBox是FancyNumber,就取出它的值,並把它從string轉換成int。 其他任何型別的FancyNumberBox都應該回傳 0。

fmt.Println(ExtractFancyNumber(FancyNumber{"10"}))
// Output: 10
fmt.Println(ExtractFancyNumber(AnotherFancyNumber{"4"}))
// Output: 0

4. 描述花俏數字盒

如果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函式!

5. 實作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
透過 GitHub 編輯 連結會在新視窗或分頁中開啟
Go Exercism

準備好開始 分類室 了嗎?

註冊 Exercism,透過 34 個概念166 個練習 和真人引導來學習並精通 Go,全部免費。