iT邦幫忙

第 11 屆 iT 邦幫忙鐵人賽

DAY 5
1
Software Development

Golang入門到進階實戰系列 第 5

Day5 數據類型與變數宣告

命名規範

Go語言中任何識別字(Identifiers) 變量、常量、函數和自定義類型等,都應該滿足以下規則:

  • 由字母、數字和下划線組成,數字不能當開頭
  • 大小寫有區分,大寫開頭可以外部呼叫,小寫開頭只能內部使用
  • 不能和Go關鍵字衝突

關鍵字

Go語言總共有25個關鍵字:

break default func interface select
case defer go map struct
chan else goto package switch
const fallthrough if range type
continue for import return var

預定義

在內建的常量、型別和函數當中有一些預定義的識別字,這些預定義的識別字並不是關鍵字,它們是可以重新定義的。

append bool byte cap close complex complex64 complex128 uint16
copy false float32 float64 imag int int8 int16 uint32
int32 int64 iota len make new nil panic uint64
print println real recover string true uint uint8 Uintptr

數據類型

Go語言的數據類型可分為基礎類型和複合類型兩大類。
基礎類型包括:布林類型、整數類型、浮點數類型、字符類型、字節串類型和錯誤類型。
複合類型包括:指針、數組、切片、字典、通道、結構體和接口。

數據類型的功能是在宣告變數時依照需求分配記憶體,當我們需要儲存大數據的時候才申請大塊的記憶體空間,如此一來就可以有效的利用記憶體資源。

布林類型

布林類型表示一個bool值,true或是false。默認值為false。

var a,b bool
a=true
b=false

整數類型

整數類型分成有符號的int和無符號的unit,默認值都是0。整數類型儲存的範圍有以下8種int8/uint8、int16/uint16、int32/uint32、int64/uint64。變數宣告時只用int/unit而無特別指定位元數時,Go語言在編釋時會依照作業系統自行判斷,32位系統為int32/unit32,64位系統為int64/uint64。

類型 存儲空間 值範圍
uint8 8-bit 0~255
uint16 16-bit 0 ~65535
uint32 32-bit 0 ~ 4294967295
unit64 64-bit 0 ~ 18446744073709551615
int8 8-bit -128 ~ 127
int16 16-bit -32768 ~ 32767
int32 32-bit -2147483648 ~ 2147483647
int64 64-bit -9223372036854775808 ~ 9223372036854775807

浮點數類型

Go語言的浮點數類型有兩種float32和float64。

浮點數比較和運算時會涉及精度問題,預設情況下float32的精度是小數後7位,float64的精度是小數後15位。

字符類型

根據官方定義,Byte等同於unit8。

uint8 the set of all unsigned 8-bit integers (0 to 255)
byte alias for uint8

Byte可以定義slice,[]byte也可以轉換成string。

字符串型

字符串是用一對雙引號""或單引號''來定義,類型是stirng,默認值是空值""。Go語言的字符串都採用 utf-8 編碼。
要注意字符串提不可修改的,遇到需要修改字符串的情境時,可以使用切片,或是轉換成[]byte修改完畢後再轉回字符串類型來達到目的。

錯誤類型

Go和C語言一樣都採用了返回值作為錯誤處理的方式,與C不同的地方是Go並不是回傳一個整數類型(errno)作為判斷依據 ,而是實現了一個錯誤類型。

err返回值除了nil以外都代表發生錯誤。

變數宣告

宣告變數時如果未賦值,Go語言默認給變數賦予當前類型的空值。宣明變數的方式有以下三種

宣告語法 說明
var name 宣告單個變數
var name1, name2,... 宣告多個變數
name := value 宣告變數並賦值;Go語言在編釋時會根據賦值來推斷變數類型
name1, name2,... := value1, value2,... 同時宣告多個變值並賦值,

其中:=宣告同時賦值的語法只在func內可以使用。

此外,變數宣告和賦值可以合併於同一行

var a int = 15
var b bool = false
var str string = "Hello world"

變數宣告時同時賦值,可以不給定變數類型,Go語言會在編釋時由所賦值的數據類型自動判斷。

var a  = 15 //type(a) int
var b  = false //type(b) bool
var str  = "Hello world" //type(str) string

我們也可以用var()函數宣告多個變數

var (
    a = 15
    b = false
    str = "Hello World"
    numShips = 50
    city string
)

指針

每個變數都有一個記憶體位置儲存該數據類型的值,指針的值可以用來儲存任何一個變數的記億體位址,它在32位機器上占用4個byte,在64位機器上占用8個byte,占用的大小和指針所指向的變數大小無關。我們也可以在使用時在指針加上一個前綴*來獲取指針所指向的變數內容。使用一個指針引用一個值稱為間接引用。

當指針被宣告後沒有賦值時,它的默認為nil,指針變數通常縮寫為ptr。
在Go語言裡,我們使用會將變數加上前綴&來進行獲取記憶體位址的操作,格式如下:

ptr := &v

其中v代表變數,&v的操作是獲取v所在的記憶體位址,並且賦值給指針ptr。

垃圾回收機制

垃級回收(Garbage Collection,簡稱GC)是高級語言中的記憶體管理功能。

在傳統的程式語言中,程序員宣告了一個變數,就是在記憶體中分派了一段相應的空間供變數儲存值。由於記憶體大小是有限的,因此當程序不再使用某個變量時,就需要銷毀該對象並釋放其所占用的資源。

在C/C++中,釋放記憶體需要用程序員自行處理,也就是程序員認為該變數不用了,就手動將其記憶體空間釋放出來。如果程序員忘記釋放記憶體或是在不該釋放的時候就銷毀變數對象,都會是非常順痛的問題。

為了解決這個問題,後來的語言都引入了自動內存管理功能,程序員不再需要關注記憶體釋放的問頭,virtual machine會自動回收不再使用的對象和釋放記憶體,這個功能就被稱為垃圾回收,

Go的GC演化過程如下:
v1.1 STW
v1.3 Mark STW, Sweep 并行
v1.5 三色標記法
v1.8 hybrid write barrier

Go語言使用的是三色標記法,這是標記清除演法法的一個改進版本,一開始所有對象都為白色,接著從根出發遍歷所有對象並標記為灰色,將標記的灰色對象放進隊列裡頭,把灰色對象從隊列裡依次取出,將引用對象和灰色對象自身都榭記為黑色,待灰色隊列為空時,所有的白色對象即為垃圾。

Go的GC觸發條件有兩個,第一是事件觸發,當記憶體使用多一位時啟動GC,第二是定時觸發,默認每兩分鐘執行一次。除此之外我們也可以手動調用GC: runtine.FC()。

https://ithelp.ithome.com.tw/upload/images/20190920/201206984ieVhSbhBx.jpg

GC可視化

https://ithelp.ithome.com.tw/upload/images/20190920/201206981YfcgWNymc.jpg
如果從GC的角度出發進行Go的性能優化,有兩個方向可以進行,第一個是少用string的"+",第二個是小對象儘量重覆使用,局部變數少宣告,多個小對象可以放到struct裡頭,以便GC的掃描。


上一篇
Day4 源碼組成與Go tools
下一篇
Day6 資料結構 Array & Slice
系列文
Golang入門到進階實戰30

尚未有邦友留言

立即登入留言