[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 结构体实例 结构体类型
~~~