## 一、init函數
官方對于init()函數的介紹:
> 變量除了可以在全局聲明中初始化,也可以在 init ()函數中初始化。這是一類非常特殊的函數,它不能夠被人為調用,而是在每個包完成初始化后自動執行,并且執行優先級比 main 函數高。 初始化總是以單線程執行,并且按照包的依賴關系順序執行。 一個可能的用途是在開始執行程序之前對數據進行檢驗或修復,以保證程序狀態的正確性。
簡單總結:
1. init函數可以在任何包中有0個、1個或多個;
2. main函數只能在main包中有且只有一個,但是main包中也可以有0個、1個或多個init函數;
3. init函數和main函數都不能被顯式調用;
## 二、#Go語言中變量、init函數、main函數的執行順序
1. 首先初始化導入包的變量和常量
2. 然后執行導入包的init函數
3. 然后初始化本包的變量和常量
4. 然后執行本包的init函數
5. 最后執行本包的main函數
## 三、如何修改字符串的內容呢?
1. 將字符串轉成byte切片,再根據下標替換內容
2. 將字符串轉為rune切片,再根據下標替換內容
3. 使用原生包`strings`中的`Replace()`方法
```
package main
import (
"fmt"
"strings"
)
func main() {
//第一種方法 將字符串轉成byte切片
s := "hello"
s2 := []byte(s)
s2[0] = 'x'
fmt.Printf("轉成byte切片:%v\n", string(s2)) //打印結果:轉成byte切片:xello
// 第二種方法 將字符串轉為rune切片
s3 := "王中陽"
s4 := []rune(s3) //注意:中文字符串要進行修改,只能轉成rune切片,不能轉成byte切片
s4[0] = '楊'
fmt.Printf("轉成rune切片:%v\n", string(s4)) //打印結果:轉成rune切片:楊中陽
// 第三種方法,使用原生包strings 中的 Replace() 方法
s5 := "abcdef"
old := "abc"
newString := "ABC"
s6 := strings.Replace(s5, old, newString, -1) //最后一個參數n的作用是:返回將s5中前n個不重疊old子串都替換為new的新字符串,如果n<0會替換所有old子串。
fmt.Printf("strings替換之后的:%v\n", s6) //打印結果:strings替換之后的:ABCdef
}
```
## 四、切片
切片由三部分組成:指針、長度(len)、容量(cap)
## 五、映射
map(hash table) —**無序集合**,key必須是可以比較的(除了浮點數,這不是一個好的選擇)
```
x := make(map[string]int)
y := map[string]int{
?"alice": 12,
?"tom": 34
}
z := map[string]int{}
// 內置函數
delete(y, "alice")
```
## 六、結構體
```
type Point struct {
?x, y int
}
type Circle struct {
center Point
?radius int
}
type Wheel struct {
?circle Circle
?spokes int
}
w := Wheel{Circle{Point{8, 8}, 5}, 20}
w := Wheel{
circle: Circle{
center: Point{x: 8, y: 8},
radius: 5,
},
spokes: 20,
}
```
## 七、JSON
```
// 將結構體轉成存放json編碼的byte切片
type Movie struct {
Title string
Year ?int ?`json:"released"` // 重定義json屬性名稱
Color bool `json:"color,omitempty"` // 如果是空值則轉成json時忽略
}
data, err := json.Marshal(movie)
data2, err := json.MarshalIndent(movie, "", " ")
// 輸出結果
{"Title":"s","released":1,"color":true}
{
"Title": "s",
"released": 1,
"color": true
}
// json解碼
content := Movie{}
json.Unmarshal(data, &content)
fmt.Println(content)
```
## 八、默認值
在go語言中:
* 布爾類型的零值(初始值)為`false`
* 數值類型的零值為`0`
* 字符串類型的零值為空字符串`""`
除此之外其它類型的默認值為`nil`,`nil`可以代表下面這些類型的零值:
* 指針類型(包括`unsafe`中的)
* `map`類型
* `slice`類型
* `function`類型
* `channel`類型
* `interface`類型
`不同類型的 nil 是不能比較的`
` 兩個相同類型的 nil 值也無法比較`
## 九、值類型和引用類型
#### 1、值類型有哪些
基本數據類型都是值類型,包括:int系列、float系列、bool、字符串、數組、結構體struct。
#### 2、引用類型有哪些?
指針、切片slice、接口interface、管道channel
#### 3、值類型和引用類型的區別?
1. 值類型在內存中存儲的是值本身,而引用類型在內存中存儲的是值的內存地址。
2. 值類型內存通常在棧中分配,引用類型內存通常在堆中分配。
## 十、要檢查切片是否為空
```
len(s) == 0
```
## 十一、make
make也是用于內存分配的,區別于new,它只用于slice、map以及channel的內存創建,而且它返回的類型就是這三個類型本身,而不是他們的指針類型,因為這三種類型就是引用類型(指針類型),所以就沒有必要返回他們的指針了。
#### 特點
make函數是無可替代的,我們在使用slice、map以及channel的時候,都需要使用make進行初始化,然后才可以對它們進行操作。
## 十二、go的map實現排序
go語言的map類型底層是有hash實現的,是無序的,不支持排序。
#### 1、解決思路
排序map的key,再根據排序后的key遍歷輸出map即可。
流程:
- 取出map中的所有key存入切片keys
- 對切片進行排序
- 按照排序后的key遍歷map
## 十三、數組
數組是具有連續內存的相同類型的集合。數組類型定義指定長度和元素類型。數組的主要問題是它們的大小是固定的——它們不能調整大小,因為數組的長度是它們類型的一部分。
## 十四、運行時間
```
~~~
start := time.Now()
end := time.Now()
fmt.Println(end.Unix()-start.Unix(), "seconds")
~~~
```
## 十五、golang的優勢
1. Go語言有著C的執行性能,Python的開發效率
2. Go語言是區塊鏈技術的首選編程語言
3. Go天生支持高并發編程
4. Go語言的應用領域廣:云計算、大數據、微服務、高并發等領域。
## 十六、Go都能做什么
> web開發、網絡編程
大量優秀的Web框架如Echo、Gin、Iris、beego等,而且 Go 內置的 net/http 包十分的優秀;
> 服務端開發
使用 C 或者 C++ 做的那些事情,用 Go 來做很合適,例如日志處理、文件系統、監控系統等;
> 爬蟲及大數據
Go語言天生支持并發,所以十分適合編寫分布式爬蟲及大數據處理;
> Paas云平臺領域
Kubernetes和Docker Swarm等;
> 分布式存儲領域
etcd、Groupcache、TiDB、Cockroachdb、Influxdb等;
> 區塊鏈領域
區塊鏈里面有兩個明星項目以太坊和fabric都使用Go語言;
> 容器技術
大名鼎鼎的Docker就是使用Go語言實現的;