# [筆記] Golang 基礎 ### 基本特性 * 泛用的程式語言 * 強調效能 * 易學 * 垃圾回收 ( 內存管理 ) * 編譯語言 ( Compiled language ) ### 安裝 下載地址 : [Golang 官方網址](https://golang.org/dl/) ### 流程 1. 撰寫程式 ```go= package main //可執行的程式必須使用 main import "fmt" //載入內建 fmt 封包,用來做基本輸出輸入 func main() { fmt.Println("Hello") } ``` 2. 建置 ( build ) : `go build <檔名>.go` ![](https://i.imgur.com/PPNK5AY.png) * 建置完會出現 `.exe` 檔 3. 執行程式 : 直接在終端機打上 `./` + `.exe` 檔的檔名 ![](https://i.imgur.com/rNTc4GS.png) ### Workspaces * src : 放置原始碼檔案 * pkg : 放置使用到的函式庫 * bin : 放置執行檔 ### 資料、資料型態、變數 #### 資料型態 * int : 整數 ( int8、int16、int32、int64、uint8、uint16... ) * float64 : 浮點數 ( float32、complex128 ) ```go= var x complex128 = complex(1, 2) //1 + 2i ``` * string : `""`,字串 * String package ```go= Compare(a, b) //比較 a 與 b 字串 Contains(str, substr) //判斷 str 是否包含 substr HasPrefix(str, prefix) //判斷 prefix 是否為 str 的前置字元 Index(str, substr) //判斷 substr 在 str 第一個出現的位置 Replace(str, old, new, n) //將 str 前 n 個 old 替換成 new TrimSpace(str) //去掉 str 頭尾的空白 ToUpper(str) //轉成大寫 ToLower(str) //轉成小寫 ... ``` * Strconv package ```go= Atoi(str) //將字串轉換為數字 Itoa(num) //將數字轉換為字串 FormatFloat(f, fmt, prec, bitSize) //將浮點數轉換為字串 ParseFloat(str, bitSize) //將字串轉換為浮點數 ... ``` * bool : 布林值 * rune : `''`,字元,實際存放整數,所以印出來會是整數 * Unicode package ```go= IsDigit(r rune) //判斷 r 是否為十進制數字 IsSpace(r rune) //判斷 r 是否為空白 IsLetter(r rune) //判斷 r 是否為字母 IsLower(r rune) //判斷 r 是否為小寫 IsPunct(r rune) //判斷 r 是否為符號 ToUpper(r rune) //轉成大寫 ToLower(r rune) //轉成小寫 ... ``` #### 資料型態轉換 `type(變數)` : 以資料型態把變數括起來,例如 : ```go= int32(x) ``` #### 變數宣告 ```go= var <變數名稱> <資料型態名稱> //宣告變數 var <變數名稱> = 100 //宣告變數並賦予值,自動判別型別 <變數名稱> := 100 //宣告變數並賦予值,自動判別型別 ``` * const ```go= const <變數名稱> = 100 //const 宣告為固定值,不可改變 const ( //多個 const 宣告 <變數名稱> = "Hi" <變數名稱> = 1000 ) ``` * iota ```go= const ( <變數名稱> = iota //0 <變數名稱> //1 ) ``` iota 初始為 0,每次 const 都會讓 iota 初始化 #### 資料型態重命名 ```go= type IDnum int //重命名後,int 還是可以用 var pid IDnum ``` * 重命名後就可以使用新的資料型態名稱來宣告變數 #### 變數可視範圍 ( Variable Scope ) GO 裡面是以 `{}` 來分隔區塊的 * Universe block : 整個 GO 的程式碼 * Package block : package 內的程式碼 * File block : 檔案內的程式碼 * if、for、switch... : 語法內的程式碼 * switch、select 內的子句 : 子句內的程式碼 ### 基本輸入與輸出 #### 載入內建封包 ```go= import "fmt" ``` #### 從終端介面輸入 ```go= fmt.Scanln(&變數名稱, &變數名稱, ...) //以換行為結束 fmt.Scan(&變數名稱, &變數名稱, ...) //以換行或空白為結束 fmt.Scanf("變數格式,EX : %d", &變數名稱) //跟 C 語言的用法一樣 ``` * `&變數名稱` : 取得變數的指標 ( Pointer ) #### 印出到終端介面 ```go= fmt.Println(資料, 資料, ...) //換行 fmt.Print(資料, 資料, ...) //不換行 fmt.Printf("變數格式,EX : %d", 變數名稱) //跟 C 語言的用法一樣 ``` ### 指標 ( Pointer ) * `&` : 傳回變數或函式的地址 * `*` : 傳回此地址的值 ```go= var x int = 1 var y int var ip *int //ip is pointer to int ip = &x //ip now points to x y = *ip //y is now 1 ``` * `new()` : 這個函式用來創建變數,並給予變數指標 ```go= ptr := new(int) *ptr = 3 ``` ### 結構控制 #### if ```go= if <條件> { //條件沒有小括弧 <待執行程式> } ``` #### for loops ( Go 沒有 while,for 是唯一的循環語句 ) ```go= for <初始值>;<結束值>;<更新值> { <待執行程式> } ``` ```go= <初始值> for <結束值> { //類似 while <待執行程式> <更新值> } ``` #### switch ```go= switch <變數> { //Go 不需要 break case <變數為此執行此行>: <待執行程式> case <變數為此執行此行>: <待執行程式> default: <待執行程式> } ``` ```go= switch { //switch 不用變數 tag 時,類似 if、else if case <條件>: <待執行程式> case <條件>: <待執行程式> default: <待執行程式> } ``` ### 複合型別 #### Arrays * 固定空間的元素集合 * 以 `[]` 宣告與表示 * 索引從 0 開始 * 初始值為 0 或空字串 ```go= var x [5]int x[0] = 2 fmt.Printf(x[1]) //印出為 0 ``` ```go= var x [5]int = [5]{1, 2, 3, 4, 5} ``` * 宣告並給予初始值 ```go= x := [...]int {1, 2, 3, 4} ``` * `...` 可以用於不定數 ```go= x := [3]int {1, 2, 3} for i, v range x { fmt.Printf("ind %d, val %d", i, v) } ``` * 在 for loop 使用 `range`,`range` 會回傳兩個數值,索引值與此索引內的值 #### Slices * 可動態的增加空間,不需像 array 一樣指定大小 * 由三個元件組成 * Pointer : 指向一個 array 的指標 * Length : 資料實際長度,`len()` 可傳回 Slice 的長度 * Capacity : 容量,`cap()` 可傳回 Slice 的容量 ```go= arr := [...]string {"a", "b", "c", "d", "e", "f", "g"} s1 := arr[1:3] //{"b", "c"} s2 := arr[2:5] //{"c", "d", "e"} ``` * s1、s2 為 Slices ```go= sli := []int {1, 2, 3} ``` * 宣告方法,也可以不給予初始值 ```go= sli1 = make([]int, 10) //len = cap = 10 sli2 = make([]int, 10, 15) //len = 10,cap = 15 ``` * 使用 `make()` 宣告 ```go= sli = make([]int, 0, 3) sli = append(sli, 100) //len 會跟著增加 ``` * 使用 `append()` 增加 Slice 內的元素 #### Hash Tables * Key 和 value * 優點 : * 較快的搜尋速度 : 比起 list 一個一個找快很多 * 有意義的 Key : Key 非整數,是可以命名的字串,在撰寫程式時較容易辨別 * 缺點 : * 可能會有碰撞 : 兩個 Key hash 到同個位置,碰撞會使程式慢上一些,但發生機率極低 ![](https://i.imgur.com/95GqlGl.png) #### Maps ```go= var idMap1 map[string]int //宣告 idMap2 = make(map[string]int) //以 make() 宣告 idMap3 := map[string]int { //宣告並給予值 "joe" : 123 } ``` * 宣告 ```go= fmt.Println(idMap["joe"]) ``` * 使用 ```go= idMap["jane"] = 456 ``` * 新增 ```go= delete(idMap, "joe") ``` * 刪除 ```go= id, p := idMap["joe"] fmt.Println(len(idMap)) ``` * id 為 value,p 為是否存在此 Key,存在為 true * `len()` 可查看此 Map 有多少鍵值對 ```go= for key, val := range idMap { fmt.Println(key, val) } ``` * Map 在 for loop 的應用 #### Structs * 多種資料型態的集合 ```go= type struct Person { name string addr string phone string } var p1 Person ``` * 宣告 ```go= p1 := new(Person) ``` * 以 `new()` 宣告並初始化 ```go= p1 := Person(name : "joe", addr : "a st.", phone : "123") ``` * 宣告並賦予值 ```go= p1.name = "joe" x = p1.addr ``` * 賦予值與使用 ### 協定與格式 #### RFC ( Requests for Comments ) ```go= import "net/http" http.Get(www.uci.edu) ``` * 使用 HTTP 協定,GET、POST、PUT...等等 ```go= import "net" net.Dial("tcp", "uci.edu:80") ``` * 使用於 TCP/IP 連線與撰寫 socket 程式 #### JSON ( JavaScript Object Notation ) * 是一種屬性鍵值對,類似 struct 或 map * 鍵值可以是任意基本資料型態,Bool、Number、String、Array...等等 * unicode 編碼 * RFC 之一 * 可以結合多種資料型態 ```go= p1 := Person(name : "joe", addr : "a st.", phone : "123") ``` * struct ```json= { "name":"joe", "addr" : "a st.", "phone" : "123" } ``` * JSON,相當於上面的 struct ```go= import "encoding/json" barr, err := json.Marshal(p1) ``` * 將 struct `p1` 轉換成 JSON 格式 ```go= var p2 Person err := json.Unmarshal(barr, &p2) ``` * 將 JSON 格式轉換成 go object 放進 `p2` * 會自動適應 Person 的各項屬性,若無會回傳 err #### File **ioutil** ```go= import "ioutil" data, e := ioutil.ReadFile("test.txt") ``` * ReadFile 可以讀取檔案內容,不須開啟與關閉檔案,如果檔案過大可能會造成錯誤 ```go= data = "Hello, world" err := ioutil.WriteFile("outfile.txt", data, 0777) ``` * WriteFile 會創建一個檔案並寫入資料後關閉,`0777` 為權限 **os** ```go= import "os" f, err := os.Open("dt.txt") //開啟檔案 barr := make([]byte, 10) nb, err := f.Read(barr) //讀取檔案前 10 byte 進 barr,nb 為讀取多少 byte f.Close() //關閉檔案 ``` * 開啟檔案後,讀取並關閉 ```go= f, err := os.Create("outfile.txt") barr := []byte{1, 2, 3} nb, err := f.Write(barr) nb, err := f.WriteString("Hi") //寫入字串 ``` * 創建檔案並寫入 ###### tags: `筆記` `程式語言` `Golang`