一文看懂 Go 的數據類型

每一門語言都有自己的數據結構,Go 語言也不例外,總共有四大類,基礎類型、聚合類型、引用類型和接口類型。本文簡單介紹一下這些類型。

  1. 基礎類型

整型

Go 的整型分爲有符號和無符號整數。

有符號整數會分成 int8、int16、int32、int64

無符號整數會分成 uint8、uint16、uint32、uint64

但通常會直接使用 int 和 uint,因爲這兩種類型會根據平臺的特性,自動轉成運算效率最高的類型,現在 32 位以下的計算機很少見了,所以 int 通常是 32 或者 64 位,但具體要根據平臺和編譯器決定。

int 是目前使用最廣泛的數值類型,在需要明確指定數值位數的時候,直接使用 int 就可以。

通常來說,有符號的整數就夠用,無符號整數只有在位運算或者特定算數的時候纔會使用。

uintptr 和 rune 是兩類特殊的數字類型,uintptr 大小不明確,用來存儲指針,主要用於底層編程,比如用於 Go 語言與 C 語言的交互。

如果兩個值可以使用 == 和 != 進行比較,說明這個兩個值是可比較的。

整數是可比較的。

其他數字類型

除了整型數據之外,Go 語言中,還有兩種數據類型:浮點數複數

浮點數有 float32 和 float64 兩種類型,浮點數一般使用指數表示法,使用 e 或者 E 來表示。

float32 的正數範圍是 1.4e-45 ~ 3.4e38

float64 的正數範圍是 4.9e-324 ~ 1.8e308

在 10 進制下,float64 的有效數字是 15 位,遠遠超過了 float32 的 5 位,如果沒有特殊的情況,應該優先使用 float64。

複數也有兩種 complex64 和 complex128,這兩種類型分別由 float32 和 float64 構成。math/cmplx 庫提供了複數運算所需要的函數。

浮點數和複數都是可比較的。

字符串

字符串可是說是最常用的數據類型。字符串由不可變的字節序列([]byte)構成,字符串的內容通常會用 UTF-8 的編碼格式處理,這點在上一篇文章中已經詳細的說明過了。

Go 的字符串內容是不可變的,對當前字符串做的操作都會生成一個新的字符串。Go 字符串天然支持 UTF-8,而且習慣上也會優先使用這種編碼方式,亂碼的煩惱會少一些。

Go 語言也爲字符串提供了豐富的類庫:

字符串是可比較的。

布爾值

布爾值相對來說比較簡單,只有兩個值:truefalse。可以使用 ! 符號來進行取反運算,!true 就是 false。

也可以使用 && 和 || 來進行組合運算,在組合運算中,也會遵循短路行爲,短路行爲是指左邊如果能直接確定最後的結果,那麼後面的計算將不會進行,如下:

var i = 1
// i < 100 代碼就不會被執行
if i > 0 || i < 100 {
    fmt.Printf("result %+v", i)
}

布爾值是可比較的。

  1. 聚合類型

聚合類型的值由內存中的一組變量構成。數組和結構體都是聚合類型,數組和結構體的長度都是固定的。數組中的的元素類型必須相同,而結構體中的元素可以不同

數組

數組是一個長度固定,擁有 0 個或多個(不超過數組長度)相同數據類型的序列。數組在聲明的時候必須指定長度,可以使用常量,但是不能使用變量。

實際上,我們很少在代碼中直接使用數組,數組在絕大部分的時候都是做爲 slice 的底層存儲,並不會直接使用。

數組的可比較性取決於元素的可比較性,如果元素是可比較的,那麼數組也是可比較的,反之亦然。

結構體

結構體是由任意個任意類型的變量組合在一起的數據類型,和其他語言中的概念相似。

type Student struct {
    Name string
    age  int
}

Go 語言是一個面向對象的語言,但卻又拋棄了 Java 中類和對象的概念,結構體是 Go 語言實現面向對象的基礎之一,還有一部分是接口,下面會聊到。

在 Go 的面向對象中,已經擯棄了繼承的概念,但在結構體中,通過結構體嵌套,也算是實現了部分繼承的功能。

結構體的可比較性也取決於其中變量的可比較性。

  1. 引用類型

引用是另外一種數據類型,很多 Go 語言的高級功能都依賴引用。引用都間接指向變量或者狀態,通過引用來操作數據會讓該數據的全部引用都受影響。

指針

指針是一種數據類型,指針的值是一個變量的地址。對於一個變量來說,可以有多個指針,通過其中任意一個指針來修改數據,通過其他指針也會獲取到最新修改的值。

i := 1
p1 := &i
p2 := &i
*p1 = 2
fmt.Println(*p2) // 2

指針是可比較的。

slice

slice 是一個擁有相同元素的可變長度序列。slice 看起來與數組很像,但本質上不同。

slice 依賴數組,沒有數組,就沒有 slice。

一個 slice 有三個屬性,指針,長度和容量。其中指針指向數組中的某個元素(不一定是第一個),這是 slice 可以訪問的第一個元素。

長度是 slice 中元素的個數,不能超過容量,容量通常是指 slice 指針的位置,到底層數組的最後一個元素的位置的長度。

slice 不可比較, 只能和 nil 比較。

map

map 是散列表的引用。

map 的使用很簡單,但是需要注意一點,map 的 key 必須是可比較的,如果 key 不可比較,那就無法通過 key 查詢到響應的 value,value 的類型是沒有限制的,可以是任意值。

map 不可比較,只能和 nil 比較。

function

function 就是函數,在寫 Go 的 helloworld 程序時,就會用到函數。函數也是一種引用類型。

function 本身不可比,只能和 nil 比較,但是可以通過反射獲取函數指針進行比較。

channel

Go 語言天然支持高併發。而 channel 就是其中關鍵一環,goroutine 用來併發執行任務。而 channel 則用來連接不同的 goroutine。channel 也是屬於引用類型。

channel 是可比較的。

  1. 接口類型

Go 語言中還有一個類型是接口類型。

接口是 Go 實現面向對象的關鍵。Go 的接口類型很特別,你不需要去顯示的實現一個接口,只要把接口中的方法實現,就默認實現了這個接口。

接口類型是可比較的。

  1. 小結

Go 的數據類型設計簡潔,但擴展性很好,開發者可以根據自己的需要動態的擴展數據,不只是對於結構體這種聚合數據類型,即使對於基礎數據類型,也可以根據的需要進行擴展。另外 Go 自帶對 JSON、xml 以及 Protocol Buffer 的支持,不需要引入外部的庫,這就使得寫程序時會很輕量級,可以儘可能少的引入依賴包。

文 / Rayjun

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/UxsVkGISnYKpCS3I_ISehA