ThinkChat🤖让你学习和工作更高效,注册即送10W Token,即刻开启你的AI之旅 广告
[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 结构体实例 结构体类型 ~~~