Go 程式設計教學:變數 (Variable) 和資料型別 (Data Type)

PUBLISHED ON SEP 7, 2017 — PROGRAMMING

    在上一篇文章中,我們談到如何建立 Go 專案,並且開始撰寫第一個程式,相信讀者都已經實際操作過了。接著,我們就要開始談程式設計最基本的部分:變數 (variable) 和資料型別 (data type)。電腦程式很大一部分是在操作各種資料 (data),本文會以程式設計的角度來討論這個議題。

    變數 (Variable)

    在撰寫程式時,我們會將資料存在變數中,在後續的程式中可呼叫該變數。可以將變數想成一個帶有標籤的盒子,變數名稱是標籤,而變數內部存的是值 (value),也就是資料。在程式中,我們透過變教來存取資料。

    我們以一個簡單的例子來展示變數的使用:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        // Declare the variable “name”.
        var name string
       
        // Assign a string value to it.
        name = "Michael"
     
        // Call the variable.
        fmt.Println("Hello, ", name)
    }
    

    變數有三個要素:

    • 變數名稱
    • 資料型別

    以本例來說,對照如下:

    • 變數名稱:name
    • 資料型別:string
    • 值:"Michael"

    宣告變數使用 var 關鍵字。在這個例字中,我們宣告變數 name,並宣告其資料型別為 string 。接著,我們指派 (assign) 字串 “Michael” 給變數 name,指派使用等號 =。最後,我們在程式中呼叫變數 name

    由於宣告變數及指派值是常見且基本的動作,Go 提供另一個語法,如下例:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        // Declare a variable and assign it some string value.
        name := "Michael"
     
        // Call the variable.
        fmt.Println("Hello, ", name)
    }
    

    在這個例子中,我們省略變數的型別,Go 會用變數的值自動判定變數的型別。為什麼 Go 要刻意使用這種語法而不直接採用等號?這可能是要在視覺上有所區別,便於日後觀看程式碼時了解程式的意圖,一部分程式設計者覺得這個語法有些冗餘。

    如果我們沒有指派變數的值,Go 會根據不同的資料型別自動指派相對應的初始值;然而,這個初始值通常不會是我們所要的值。一般來說,大部分 Gopher 會用第二種方法宣告變數,只有在需要時才用第一種方法宣告變數。

    Go 宣告變數有以下四種方式:

    • var:宣告變數 (variable)
    • const:宣告常數 (constant)
    • func:宣告函式 (function)
    • type:宣告新型別

    我們已經看過 var 了,而 const 用來宣告常數,常數宣告後即不可變動。以下是範例:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        // Declarethe a constant PI, assigning it a value.
        const PI = 3.14159
     
        // Call the variable.
        fmt.Println("PI: ", PI)
    }
    

    習慣上,常數會使用全大寫,像是 CONSTANT_NAME。這個範例僅是用來展示如何宣告常數,實際上,math 套件有一個更精準的圓周率常數 math.Pi,我們不該另外宣告一個。

    關鍵字 func 是用來宣告函式,就像我們宣告主函式一般;type 則是用來宣告新型別。我們將於後續文章中介紹。

    資料型別

    Go 變數會帶有相對應的型別,型別可以規範變數在程式中相對應的動作,例如,數字可以加減乘除,布林值可進行邏輯運算等。Go 有以下四大類型別:

    • 基本型別 (basic types)
    • 聚合型別 (aggregate types)
    • 參考型別 (reference Types)
    • 介面型別 (interface types)

    基本型別包括以下數種型別:

    • 整數 (integers)
      • 有號:int8, int16, int32, int64, int
      • 無號:uint8, uint16, uint32, uint64, uint
      • rune,內部為 int32,表 unicode code point
      • byte,內部為 uint8,表一段 raw data
      • uintper,儲存記憶體位置
    • 浮點數 (floating-point numbers)
      • 單精度 (6 位精確度):float32
      • 倍精度 (15 位精確度):float64
    • 複數 (complex numbers)
      • 單精度:complex64,由 32 位元的實數和虛數組成
      • 倍精度:complex128,由 64 位元的實數和虛數組成
    • 字串 (string)
    • 布林值 (boolean)

    雖然數字型別有很多種,這是為了節省運算資源,對於一般使用者來說,不需要去細別數字的型別,整數用 int,浮點數用 float64 即可。如果需要用 Go 進行大數 (big number) 運算,則需使用 math/big 套件,因為電腦內部無法直接表示大數,需要用軟體去模擬。

    要注意的是,Go 程式在數字過大過小時會溢位 (overflow) 或下溢 (underflow),這是由於電腦內部表示數字的方式所帶來的限制。實例如下:

    package main
     
    import (
        "fmt"
        "math"
    )
     
    func main() {
        // num is the maximal int32 value.
        num := math.MaxInt32
     
        // Get -2147483648.
        fmt.Println(num + 1)
    }
    

    在大部分的情形下,溢位不是我們期待的結果,但 Go 目前沒有特別的方法防止溢位,如果預期數字會比較大,可能要用較大位數的型別或是轉用大數運算套件。

    在 Go 程式中,不能直接將不同型別的數字相加,會引發錯誤。見以下實例:

    package main
     
    import (
        "fmt"
    )
     
    func main() {
        // a is an integer
        a := 1
     
        // b is a floating-pointing number
        b := 2.0
     
        // Error: mismatched types.
        fmt.Println(a + b)
    }
    

    解套的方式是將其中一個變數轉型,Go 提供 int()float32()float64() 等內建函式可進行轉型的動作。

    Go 提供以下聚合型別:

    • 陣列 (array)
    • 結構 (struct)

    透過聚合型別,單一變數可容納多個值。我們將會後續文章中介紹,目前暫不說明。

    Go 提供以下參考型別:

    • 指標 (pointer)
    • 切片 (slice)
    • 字典 (map)
    • 函式 (function)
    • 通道 (channels)

    參考型別的內部使用指標 (pointer),同樣地,我們會於後續文章中另行介紹。

    經過本文,讀者應該對變數和資料型別有一些概念。我們將在下一篇文章中介紹運算子 (operator),透過運算子,可以進一步操作資料,達成更多的功能。

    comments powered by Disqus