[TOC]
## init函數
~~~
1 init函數是用于程序執行前做包的初始化的函數,比如初始化包里的變量等
2 每個包可以擁有多個init函數
3 包的每個源文件也可以擁有多個init函數
4 同一個包中多個init函數的執行順序go語言沒有明確的定義(說明)
5 不同包的init函數按照包導入的依賴關系決定該初始化函數的執行順序
6 init函數不能被其他函數調用,而是在main函數執行之前,自動被調用
~~~
對同一個go文件的`init()`調用順序是從上到下的。
對同一個package中不同文件是按文件名字符串比較“從小到大”順序調用各文件中的`init()`函數。
對于不同的`package`,如果不相互依賴的話,按照main包中"先`import`的后調用"的順序調用其包中的`init()`,如果`package`存在依賴,則先調用最早被依賴的`package`中的`init()`,最后調用`main`函數。
如果`init`函數中使用了`println()`或者`print()`你會發現在執行過程中這兩個不會按照你想象中的順序執行。這兩個函數官方只推薦在測試環境中使用,對于正式環境不要使用。
## 下劃線
~~~
占位符,意思是那個位置本應賦給某個值,但是咱們不需要這個值。
所以就把該值賦給下劃線,意思是丟掉不要。
這樣編譯器可以更好的優化,任何類型的單個值都可以丟給下劃線。
這種情況是占位用的,方法返回兩個結果,而你只想要一個結果。
那另一個就用 "_" 占位,而如果用變量的話,不使用,編譯器是會報錯的。
~~~
## 變量聲明
### 常規聲明
~~~
var 變量名 變量類型
var name string
var age int
var isOk bool
~~~
### 批量聲明
```go
var (
a string
b int
c bool
d float32
)
```
### 短變量聲明
在函數內部,可以使用更簡略的 := 方式聲明并初始化變量。
```go
func main() {
n := 10
m := 200 // 此處聲明局部變量m
fmt.Println(m, n)
}
```
~~~
函數外的每個語句都必須以關鍵字開始(var、const、func等)
:=不能使用在函數外。
_多用于占位,表示忽略值。
~~~
## 基本類型介紹
| 類型 | 長度(字節) | 默認值 | 說明 |
| --- | --- | --- | --- |
| bool | 1 | false | |
| byte | 1 | 0 | uint8 |
| rune | 4 | 0 | Unicode Code Point, int32 |
| int, uint | 4或8 | 0 | 32 或 64 位 |
| int8, uint8 | 1 | 0 | \-128 ~ 127, 0 ~ 255,byte是uint8 的別名 |
| int16, uint16 | 2 | 0 | \-32768 ~ 32767, 0 ~ 65535 |
| int32, uint32 | 4 | 0 | \-21億~ 21億, 0 ~ 42億,rune是int32 的別名 |
| int64, uint64 | 8 | 0 | |
| float32 | 4 | 0.0 | |
| float64 | 8 | 0.0 | |
| complex64 | 8 | | |
| complex128 | 16 | | |
| uintptr | 4或8 | | 以存儲指針的 uint32 或 uint64 整數 |
| array | | | 值類型 |
| struct | | | 值類型 |
| string | | "" | UTF-8 字符串 |
| slice | | nil | 引用類型 |
| map | | nil | 引用類型 |
| channel | | nil | 引用類型 |
| interface | | nil | 接口 |
| function | | nil | 函數 |
空指針值 nil,而非C/C++ NULL。
### 字符串轉義符
> Go 語言的字符串常見轉義符包含回車、換行、單雙引號、制表符等,如下表所示。
| 轉義 | 含義 |
| --- | --- |
| \\r | 回車符(返回行首) |
| \\n | 換行符(直接跳到下一行的同列位置) |
| \\t | 制表符 |
| \\' | 單引號 |
| \\" | 雙引號 |
| \\ | 反斜杠 |
### 多行字符串
~~~
s1 := `第一行
第二行
第三行
`
fmt.Println(s1)
~~~
反引號間換行將被作為字符串中的換行,但是所有的轉義字符均無效,文本將會原樣輸出。
### 字符串的常用操作
| 方法 | 介紹 |
| --- | --- |
| len(str) | 求長度 |
| +或fmt.Sprintf | 拼接字符串 |
| strings.Split | 分割 |
| strings.Contains | 判斷是否包含 |
| strings.HasPrefix,strings.HasSuffix | 前綴/后綴判斷 |
| strings.Index(),strings.LastIndex() | 子串出現的位置 |
| strings.Join(a\[\]string, sep string) | join操作 |
## 數組Array
### 數組的定義
~~~
數組定義:var a [len]int,比如:var a [5]int,數組長度必須是常量,且是類型的組成部分。一旦定義,長度不能變。
長度是數組類型的一部分,因此,var a[5] int和var a[10]int是不同的類型。
~~~
~~~
func main() {
a := [2][3]int{{1, 2, 3}, {4, 5, 6}}
b := [...][2]int{{1, 1}, {2, 2}, {3, 3}} // 第 2 緯度不能用 "..."。
fmt.Println(arr0, arr1)
fmt.Println(a, b)
}
~~~
### 數組遍歷
一維數組遍歷
~~~
c:=[...]int{1,2,3,4,5,9}
for index,i := range c {
println(index,i)
}
~~~
多維數組遍歷
~~~
package main
import (
"fmt"
)
func main() {
var f [2][3]int = [...][3]int{{1, 2, 3}, {7, 8, 9}}
for k1, v1 := range f {
for k2, v2 := range v1 {
fmt.Printf("(%d,%d)=%d ", k1, k2, v2)
}
fmt.Println()
}
}
~~~
### 數組拷貝與傳參
~~~
package main
import "fmt"
func printArr(arr *[5]int) {
arr[0] = 10
}
func main() {
var arr1 [5]int
printArr(&arr1)
fmt.Println(arr1)
arr2 := [...]int{2, 4, 6, 8, 10}
printArr(&arr2)
fmt.Println(arr2)
}
~~~
## 指針
Go語言中的函數傳參都是值拷貝,當我們想要修改某個變量的時候,我們可以創建一個指向該變量地址的指針變量。傳遞數據使用指針,而無須拷貝數據。類型指針不能進行偏移和運算。Go語言中的指針操作非常簡單,只需要記住兩個符號:`&`(取地址)和`*`(根據地址取值)。
~~~
func modify1(x int) {
x = 100
}
func modify2(x *int) {
*x = 100
}
func main() {
a := 10
modify1(a)
fmt.Println(a) // 10
modify2(&a)
fmt.Println(a) // 100
}
~~~
## Map
### 定義
~~~
map[KeyType]ValueType
~~~
map類型的變量默認初始值為nil,需要使用make()函數來分配內存。語法為:
~~~
make(map[KeyType]ValueType, [cap])
~~~
其中cap表示map的容量,該參數雖然不是必須的,但是我們應該在初始化map的時候就為其指定一個合適的容量。
~~~
func main() {
scoreMap := make(map[string]int, 8)
scoreMap["張三"] = 90
scoreMap["小明"] = 100
fmt.Println(scoreMap)
fmt.Println(scoreMap["小明"])
fmt.Printf("type of a:%T\n", scoreMap)
}
~~~
### 判斷key是否存在
~~~
func main() {
scoreMap := make(map[string]int)
scoreMap["張三"] = 90
scoreMap["小明"] = 100
// 如果key存在ok為true,v為對應的值;不存在ok為false,v為值類型的零值
v, ok := scoreMap["張三"]
if ok {
fmt.Println(v)
} else {
fmt.Println("查無此人")
}
}
~~~
### 遍歷
~~~
func main() {
scoreMap := make(map[string]int)
scoreMap["張三"] = 90
scoreMap["小明"] = 100
scoreMap["王五"] = 60
for k, v := range scoreMap {
fmt.Println(k, v)
}
}
~~~
### 刪除key
~~~
delete(map, key)
~~~
## 自定義結構體
這個在實際開發中封裝實體的時候可以說用的十分頻繁
### 定義
~~~
type 類型名 struct {
字段名 字段類型
字段名 字段類型
…
}
~~~
### 實例化
~~~
var 結構體實例 結構體類型
~~~