Go語言中任何識別字(Identifiers) 變量、常量、函數和自定義類型等,都應該滿足以下規則:
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 |
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()。
GC可視化
如果從GC的角度出發進行Go的性能優化,有兩個方向可以進行,第一個是少用string的"+",第二個是小對象儘量重覆使用,局部變數少宣告,多個小對象可以放到struct裡頭,以便GC的掃描。