## 一、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语言实现的;