在對環境有基本的了解後,我們終於要開始說基本語法拉~如果你是已經使用過 golang 的朋友,今天可以放心跳過這篇惹。今天我們會全速通過 golang所有基本該知道的語法,因為考量到後續篇幅的關係一些常見的型態介紹會被我省略。
讓我們以最簡單的範例檔開始吧!
main.go
package main
import "fmt"
//主程式名稱固定為 main()
func main() {
fmt.Println("hello world")
}
這是我們在測試簡單函式最常使用的方式,直接下 go run 將 main func 下的程式碼跑起來,用以觀察特定結果,這在開發中針對局部函式直接執行最快的方式。
#於 main.go 同層目錄執行
> go run main.go
hello world
透過 go build 可以編譯出可執行的二進制檔,在預設不帶環境變數編譯的情況下,系統會依當機器核心編譯出相同可以執行的檔案。通常用於程式已經開發到一定階段,要上到測試環境或營運環境時使用。
#於 main.go 同層目錄執行
> go build -o hello .
> ./hello
hello world
同 go build 會編譯出可執行的二進制檔,不一樣的是他會放置於 GOPATH/bin 下,並且加入系統命令中,提供我們隨時呼叫調用。很適合用於 command line tool 的用途。
#於 main.go 同層目錄執行
> go install
#刷新terminal or 直接重開一個也行
> source ~/.bashrc
#呼叫的名稱,會依據先前編譯的目錄名稱命名
#例如我們在 /helloWorld 下編譯,即為 helloWorld
> helloWorld
hello world
以下範例檔都會統一放在 Github裏,未來如果有其他範例也會統一放在這,大家可以直接 clone 下來配合文章內容使用。
有短宣告供我們直接賦值使用,另外需特別注意部分型態像是 map ,需透過 make 實體化後方可賦值使用。
package main
//套件引用
import (
"fmt"
"time"
)
func main() {
//基本宣告,給予該型態預設值
var number int
var str string
//多變數宣告
var (
numFloat float32
numInt64 int64
)
//都會得到該型態預設值
fmt.Println("number", number)
fmt.Println("str", str)
fmt.Println("numFloat", numFloat)
fmt.Println("numInt64", numInt64)
//短宣告,可同時賦值,且型態將由賦值時自動定義
name := "Wesley"
age := 32
createTime := time.Now()
fmt.Println("name", name)
fmt.Println("age", age)
fmt.Println("createTime", createTime)
//部分變數在賦值前需 make 出來
var strMap map[string]string
strMap = make(map[string]string) //不信你可以註解掉這行
strMap["ip"] = "127.0.0.1"
strMap["host"] = "localhost"
fmt.Println("strMap", strMap)
}
迴圈在使用上除了不需要小括號以外,較需注意的是 foreach 的用法,key 會在前面 value 在後,且變數key & value 僅作用於此 for {} 範圍內。
package main
import "fmt"
func main() {
//指定範圍迴圈
fmt.Println("count 0~9")
for i := 0; i < 10; i++ {
fmt.Println(i)
}
fmt.Println()
//foreach
fmt.Println("foreach")
memberList := []string{"Wesley", "Ken", "Eric"} //a string slice
for key, value := range memberList {
fmt.Println(key, value)
}
fmt.Println()
//break loop
fmt.Println("break loop when i over 3")
for i := 0; i < 10; i++ {
if i > 3 {
fmt.Println("break at", i)
break
}
fmt.Println(i)
}
fmt.Println()
//continue
fmt.Println("use continue to skip 5")
for i := 0; i < 10; i++ {
if i == 5 {
continue //will skip code after "continue" and keep going next round
}
fmt.Println(i)
}
fmt.Println()
}
函式使用上有多回傳值特色,也提供匿名函數的使用。匿名函數多用於併發與閉包操作,至於併發與閉包特性會在後面的篇幅獨立介紹。
package main
import (
"fmt"
"strconv"
)
func main() {
//單一參數,無回傳
voidFunc("Wesley")
//多參數,多回傳
sum, err := intSum("1", "1")
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println(sum)
//匿名函式,常配合併發使用
func(f float64){
fmt.Println("π", f)
}(3.1415926)
}
//單一參數,無回傳
func voidFunc(name string) {
fmt.Println(name)
}
//多參數,多回傳
func intSum(numA string, numB string) (int, error) {
a, err := strconv.Atoi(numA)
if err != nil {
fmt.Println(err.Error())
return 0, err
}
b, err := strconv.Atoi(numB)
if err != nil {
fmt.Println(err.Error())
return 0, err
}
return a + b, nil
}
Golang 獨有的變數型態,用來傳遞已定義好的資料集,相似 C語言的 struct 或物件導向的 object。透過宣告 struct 內各個 field 的屬性與名稱,方便我們進行複雜資料集的傳遞,也可以維持資料傳遞過程中的型態一致。
package main
import "fmt"
//Client 定義 Client 型態
type Client struct {
IP string
Host string
maxConn int
}
func main() {
//回傳型態為 Client 的 struct
client := newClient("127.0.0.1", "localhost")
fmt.Printf("%+v\n", client)
//可對已實體化的 client 賦值
client.IP = "0.0.0.0"
fmt.Printf("%+v\n", client)
//可利用 pointer 的方式,pass by address
setMaxConn(&client, 100)
fmt.Printf("%+v\n", client)
//直接用短宣告實體化
client2 := Client{
IP: "192.0.0.1",
Host: "test.host",
maxConn: 3,
}
fmt.Printf("%+v\n", client2)
}
//可用於傳遞
func newClient(ip, host string) Client {
return Client{
IP: ip,
Host: host,
maxConn: 10,
}
}
//可利用 pointer pass by address 並異動
func setMaxConn(c *Client, num int) {
c.maxConn = num
}