iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 7
0

在對環境有基本的了解後,我們終於要開始說基本語法拉~如果你是已經使用過 golang 的朋友,今天可以放心跳過這篇惹。今天我們會全速通過 golang所有基本該知道的語法,因為考量到後續篇幅的關係一些常見的型態介紹會被我省略。

執行

讓我們以最簡單的範例檔開始吧!

main.go

package main

import "fmt"

//主程式名稱固定為 main()
func main() {
	fmt.Println("hello world")
}

go run

這是我們在測試簡單函式最常使用的方式,直接下 go run 將 main func 下的程式碼跑起來,用以觀察特定結果,這在開發中針對局部函式直接執行最快的方式。

#於 main.go 同層目錄執行
> go run main.go

hello world

go build

透過 go build 可以編譯出可執行的二進制檔,在預設不帶環境變數編譯的情況下,系統會依當機器核心編譯出相同可以執行的檔案。通常用於程式已經開發到一定階段,要上到測試環境或營運環境時使用。

#於 main.go 同層目錄執行
> go build -o hello .
> ./hello

hello world

go install

同 go build 會編譯出可執行的二進制檔,不一樣的是他會放置於 GOPATH/bin 下,並且加入系統命令中,提供我們隨時呼叫調用。很適合用於 command line tool 的用途。

#於 main.go 同層目錄執行
> go install
#刷新terminal or 直接重開一個也行
> source ~/.bashrc
#呼叫的名稱,會依據先前編譯的目錄名稱命名
#例如我們在 /helloWorld 下編譯,即為 helloWorld
> helloWorld

hello world

語法

以下範例檔都會統一放在 Github裏,未來如果有其他範例也會統一放在這,大家可以直接 clone 下來配合文章內容使用。

Declare

有短宣告供我們直接賦值使用,另外需特別注意部分型態像是 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)
}

Loop

迴圈在使用上除了不需要小括號以外,較需注意的是 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()
}

Function

函式使用上有多回傳值特色,也提供匿名函數的使用。匿名函數多用於併發與閉包操作,至於併發與閉包特性會在後面的篇幅獨立介紹。

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
}

Struct

Golang 獨有的變數型態,用來傳遞已定義好的資料集,相似 C語言的 struct 或物件導向的 object。透過宣告 struct 內各個 field 的屬性與名稱,方便我們進行複雜資料集的傳遞,也可以維持資料傳遞過程中的型態一致。

  • type : 用來宣告 struct 的語法,定義每個欄位的名稱與屬性
  • 大寫小寫:golang 中大小寫是有不同意義的,有作用域上的差別。大寫可視為 public,小寫可視為 private (會在明天的作用域的篇幅在解釋一次跟大家分享 )
  • pointer : 符號 & 用來取該變數的 address ,符號 * 則是該位址的 value
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
}

上一篇
Day6 Basic Go (GO MODULES)
下一篇
Day8 Basic Go (Initialize, Scope)
系列文
Go Distributed & Go Consistently30

尚未有邦友留言

立即登入留言