前言
這篇文章主要來紀錄 Golang 的學習紀錄,使用的教材是碁峰出版的精通 Go 程式設計。
正文
程式結構
名稱
Go 的命名原則: 以 字母 or 底線 開頭
Go 有若干個關鍵字,只能用於語法中使用,因此他們不能拿來當作名稱!
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
但是 Go 有一些 預先宣告 的名稱,是可以拿來重新宣告的!
常數: true false iota nil
型別: int uint float bool byte rune string error
函式: make len cap new append copy close delete complex real imag panic recover
名稱的第一個字母用來決定可見度是否可以跨越套件的邊界,如果名稱是以大寫字母開頭,在套件外是可見且可存取的,比方說 fmt 的 Print,套件的名稱本身永遠是小寫。
名稱長度無限制,但 Golang 的 convention 是習慣使用 短名稱 及 **駱駝式(Camel Case)**。比方說,變數 i 比 theLoopIndex 常見,或是習慣使用 aNewFunc 而不是 a_new_func。
但這一切都是使用習慣,在業界大多是還是以部門的開發文化為主!
宣告
主要有四種宣告 var const type func,以下面的程式碼來做介紹
1  | package main  | 
boilingF 屬於套件層級的宣告,而 f, c 屬於區域宣告。
變數
透過 var 來宣告特定型別的變數,格式為 var name type = expression,其中 型別 或是 = expression 兩者之一是可以省略的,但不能全部省略,如果省略型別,則會以 expression 來決定型別,如果省略 expression,則會以型別的零值來決定數值。
E.g.
數字 -> 0
布林值 > false
字串 > “”
interface & 參考型別 > nil
集合型別(array & struct) > 所有元素 or 欄位均為零值
零值的機制是為了確保變數有個正確定義的值,Go 沒有所謂的為定義變數,這麼做是為了不額外花心力的前提下確保合理的邊界條件。
1  | var s string  | 
短變數宣告
以省略 var 的方式來宣告變數,格式為 name:=expression,其中 name 的型別是由 expression 來決定。
短變數宣告中,必須至少宣告一個新的變數
1  | a, b := 1, 2  | 
指標
指的是變數的位址,因此指標是所儲存值的位置。 並非每一個數值都會有位址,但 **每個變數都會有位址
**! 因此我們可以使用指標來讀取或是修改這些值
組合型別變數 - struct or array 的元素也都具有位址
任何型別的指標,其零值皆為 nil。指標也可以拿來互相比較,當兩個指標在同一個變數或均為 nil 才會相等。
1  | var x, y int  | 
在函式中可以安全的回傳區域變數的位址,對於 foo 內的區域變數 v,在呼叫完畢之後,還是能透過指標來指向他
1  | func main() {  | 
1  | var n = flag.Bool("n", false, "omit trailing newline")  | 
new 函式
透過內建的 new 來建構變數,建構一個 x型別的不具名變數**,也就是說 new(x) 是以 x 的零值去做初始化,並回傳 *x 型別的位址。
1  | p := new(int)  | 
變數生命週期
指派
透過 指派 讓變數所保存的值進一步變化
1  | x = 1 // 具名變數  | 
資料組的指派
可以在同一行中去指派多個資料
1  | x, y = y, x  | 
1  | func main() {  | 
型別宣告
type 賦予固有的型別一個新的 具名型別,格式為 type name underlying-type,通常 name 會以大寫的方式呈現。
1  | // 以 float64 去定義新的型別 Celsius, Fahrenheit  | 
基本資料型別
Go 的型別分成四種:
- 基本型別: 數字、字串、布林
 - 集合型別: 陣列、Struct
 - 參考型別: 指標、slice、map、函式、channel
 - 介面型別
 
整數
可以分成 正負號 & 無正負號 & 四種大小 8、16、32、64 的組合。
要注意不同型別的變數不能做運算
1  | var apples int32 = 1  | 
複數
有 complex64 & complex128 這兩種。
1  | var x complex128 = complex(1, 2)  | 
字串
嘗試存取範圍外的位元組會導致 panic
1  | str := "a pine apple"  | 
可以透過 slice 來取得特定範圍的字串內容
1  | str := "a pine apple"  | 
常數
常數宣告可以指定 型別 與 值,在沒有明確指定型別時,型別由運算式的右手邊決定。
iota 常數產生器
const 宣告可使用 iota 常數產生器,這種型別也可以稱為列舉 Enum。
1  | type Weekday int  | 
1  | type Flags int  | 
組合型別
陣列
是由零到多個特定型別元素所組成的,因為它是固定長度,故陣列很少在 Go 中使用,反而可變大縮小的 slice 更有彈性。
陣列變數以元素型別的零值來做初始化
1  | var arr1 [3]int = [3]int{1, 2, 3}  | 
也可以使用 ... 來代替長度
1  | arr2 := [...]int{1, 2, 3}  | 
陣列的長度大小也是用來判定型別是否相同的一部分因素,因此,[3]int 與 [4]int 兩者是不同的型別。
1  | arr1 := [3]int{1, 2, 3}  | 
1  | 建立 int 型別的新型別 Currency  | 
雜湊表 map
雜湊表是一個無排序的 key/value 群組,在這群組中的鍵值必定唯一,其表示方法為 map[K]V,其中 K & V 所分別代表的是鍵與值的型別。所有鍵 & 值 均為同一型別,但兩者不一定要同一型別。
Goroutine & Channel
每個並行執行的都被稱為 goroutine