Go 這語言出來也好一段時間了,由於本身後端都是用 C# 在開發,一直都沒有很大的動機學習另外一個後端語言。趁著這次 GDG 台中 12 月份的大活動,來學習一波 Go 吧
歷史
Go 是由 Google 和眾多的貢獻者一起發展的開源專案 (BSD-style 授權)

安裝
依官網的安裝文件安裝,基本上是沒有問題的。編輯器的部分可以使用 VS Code + Go 的擴充套建,或是使用JetBrains GoLand 編輯器(商用)
Hello World
第一個 Go 的程式
1  | // hello-world.go  | 
透過下指令的方式就可以執行 Go 檔案,go run hello.world.go

要將 Go 建置成可以跑執行檔,執行 go build hello.world.go 之後,就可以執行 ./hello-word

如果要將 Go  打包成全域可使用的話,可透過 go install  的語法,但要使用這個前置條件是 GOBIN 的環境變數要設定,windows 就加入一個環境參數 GOBIN 並設定一個資料夾即可

基本語法
packages
go 世界裡,每一個 go 檔案都會歸屬到一個 packages 裡面,就拿上面的 hello-world 來看
1  | package main  | 
要使用其他 package 就需要透過 import
1  | import (  | 
當 package 被 import 時,就可以使用該 package 內第一個為大寫的 functions。換句話說,如果 functions 的名稱第一個是小寫的,就不會被 export 出去

上圖為使用小寫 functions 時會出現的錯誤訊息,當改使用大寫的 functions,則會是這個結果

functions
Go 的 functions 也是要定型別的,只是定型別的順序跟常見的 C# 等語言不太一樣
1  | func add(x int, y int) int {  | 
型別都定義在後方,當連續的參數都是同一型別時,也可以這樣寫
1  | func add(x, y int) int {  | 
Go 另外一個比較特別的地方就是 function 允許回傳多個值
1  | func swap(x, y string) (string, string){  | 
換另外一種命名方式回傳 (但不太建議這樣子使用)
1  | func split(sum int) (x, y int) {  | 
variables
可愛的 var 又來了
1  | package main  | 
設定預設值的方式,就在後面一順序給要的預設值就可以了,Go 會依預設值自行推斷型別
1  | var c, python, java = true, false, "no!"  | 
另外一種簡化的宣告方式,使用 :=
1  | // 原本的做法  | 
basic types
- bool
 - string
 - int int8 int16 int32 int64
 - uint uint8 uint16 uint32 uint64 uintptr
 - byte // alias for uint8
 - rune // alias for int32, represents a Unicode code point
 - float32 float64
 - complex64 complex128
 
defaultValue
各型別如果沒有給予設值的系統預設值為
- string => 「」
 - bool => false
 - 數字型 => 0
 
如果要轉型的話,可以這樣子操作 T(v) 會將 value v 轉換成 T 型別
1  | var i int = 42  | 
consts
使用 const 宣告常數值,常數值不能使用 := 宣告
1  | const Pi = 3.14  | 
流程控制
for
for 迴圈的基本起手式,不需要小括弧,但大括弧是必要的
1  | func main() {  | 
go 版本的 while,仍是用 for 表示
1  | sum := 1  | 
永不停止的寫法,還是用 for
1  | for {  | 
if
條件判斷應該是最基本的,只是不需要小括弧,但大括弧是必要的
1  | if x < 0 {  | 
更懶惰但要習慣的寫法是,在 if 內做變數指定
1  | func pow(x, n, lim float64) float64 {  | 
switch
1  | today := time.Now().Weekday()  | 
基本 switch case 都會附上 break (預設隱藏),當然要寫也是可以的,而 case 的條件也可以是 expression,這樣就不局限必須為一個數值之類的,可以是條件、function 的,以下是一些 switch case 不同的寫法
1  | func myswitch(v int) {  | 

1  | func myswitch(v int) {  | 

fallthrough: 執行完此 case 後,繼續往下走 switch case 判斷
1  | func myswitch(v int) {  | 

defer
defer 會等到周圍的 function 都執行完成後,再執行
1  | package main  | 
既然 defer 會 hold 住 function,那當好幾個 defer 時,又會怎麼執行呢
1  | package main  | 
輸出結果為

所以 defer 所堆疊起來的 functions,會採後進先出的方式執行,可以讀此文章了解更多