go的Day 04总结 内置函数,递归, 数组与切片,map,包
Day 04
内置函数
-
close
:主要用来关闭channel
-
len
:用来求长度,比如:strings
、array
、slice
、map
、channel
-
new
:用来分配内存,主要用来分配值类型内存。比如:int
、struct
。返回的是指针。var b *int b = new(int) *b = 100
-
make
:用来分配内存,主要是用来分配引用类型内存。比如:map
、channel
、slice
等类型。var c chan int c = make(chan int, 4)
make
和new
的区别:package main import "fmt" func main() { s1 := new([]int) fmt.Println(s1) s2 := make([]int, 10) fmt.Println(s2) *s1 = make([]int, 5) fmt.Println(*s1) }
-
append
:用来追加元素到数组、slice
中。对于slice 即使未初始化,也可以直接使用append方法,而未初始化的切片,不能使用 slice[index]=3这样的赋值var a []int a = append(a, 1)
-
panic
、recover
:用来做错误处理。package main import ( "fmt" "math/rand" "time" ) func testRecover(a int, b int) { defer func() { if err := recover(); err != nil { fmt.Println(err) } }() c := a / b fmt.Printf("%d / %d = %d\n", a, b, c) } func init() { rand.Seed(time.Now().UnixNano()) } func main() { for { testRecover(rand.Intn(1000), rand.Intn(10)) time.Sleep(time.Millisecond * 100) } }
递归函数
自己调用自己的函数就叫做递归。
-
阶乘
package main import "fmt" func calc(n int) int { if n <= 1 { return 1 } return calc(n - 1) * n } func main() { fmt.Println(calc(10)) }
-
Fibonacci 数列
package main import "fmt" func fibonacci(n int) int { if n <= 2 { return 1 } return fibonacci(n - 1) + fibonacci(n - 2) } func main() { fmt.Println(fibonacci(3)) }
-
递归的设计原则
-
一个大的问题能够分解的同等问题的小问题。
-
定义好终止递归的条件。
-
闭包
闭包: 一个函数和与其相关的引用环境组合而成的实体。
闭包的一个例子:
package main
import (
"fmt"
"strings"
)
func makeSuffixFunc(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
func main() {
func1 := makeSuffixFunc(".bmp")
func2 := makeSuffixFunc(".jpg")
fmt.Println(func1("hello"))
fmt.Println(func2("name"))
}
数组与切片
-
数组:是同一种数据类型的固定长度序列。
-
数组定义:
var a [len]int
,比如:var a [5]int
,数组长度一旦定义是不可变的。 -
长度是数组类型的一部分,因此:
var a[5] int
和var a [10]int
是不同的类型。 -
数组可以通过下标进行访问,下标是从0开始,最后一个元素的下标是:
len - 1
for i := 0; i < len(a); i++ { fmt.Println(a[i]) }
for _, item := range a { fmt.Println(item) }
-
访问越界,如果下标在数组合法范围之外,则触发访问越界。会 panic
-
数组是值类型,因此改变副本的值并不会改变本身的值。
-
数组初始化
var a [5]int = [5]int{1,2,3,4,5}
// 当初始化使用的数值不够的情况下,其余为 0 var a [5]int = [5]int{1,2,3,4}
var a = [5]int{1,2,3,4,5}
var a = [...]int{1,2,3,4,5}
var a = [5]string{3:"hello world", 4: "tom"}
-
多维数组
var a [4][2]int
var a [4][2]int = [4][2]int{{0, 1}, {0, -1}, {1, 0}, {-1,0}}
var a = [4][2]int{{0, 1}, {0, -1}, {1, 0}, {-1,0}}
var a [4][2]int = [...][2]int{{0, 1}, {0, -1}, {1, 0}, {-1,0}}
var a = [...][...]int{{0, 1}, {0, -1}, {1, 0}, {-1,0}}
-
多维数组遍历
package main import "fmt" func main() { var a [4][2]int = [...][2]int{{0, 1}, {0, -1}, {1, 0}, {-1,0}} for row, arr := range a { for col, val := range arr { fmt.Println(row, col, val) } } }
切片
-
切片:切片是数组的一个引用,因此切片是引用类型。
-
切片的长度可以改变,因此,切片是一个可变数组。
-
切片的遍历方式和数组一样。同样可以使用
len()
计算长度。 -
cap
可以计算slice
的最大容量。0 <= len(slice) <= cap(slice)
,其中array
是slice
引用的数组。 -
切片的定义:
var 变量名 []类型
,比如:var str []string
var a = [5]int{1,2,3,4,5} var sliceA = a[2:4] fmt.Println(a) fmt.Println(sliceA)
// 直接包含整个数组 var sliceA = a[:]
// 只说明结束为止,开始位置默认为0 var sliceA = a[:3]
// 只说明开始位置,结束位置默认为最后 var sliceA = a[2:]
-
切片的内存布局
-
通过
make
来创建切片var slice []int = make([]int, 10)
var slice []int = make([]int, 10, 100)
-
用
append
内置函数操作切片slice = append(slice, 10)
// 合并两个切片 var a []int = []int{1,2,3} var b []int = []int{4,5,6} var c = append(a, b...)
-
for range
遍历切片 -
切片
resize
-
切片的拷贝
copy
函数:copy(dst, src []Type)
-
string
与slice
string
底层就是一个byte
数组。因此,可以可以进行切片操作。 -
string
的底层布局 -
string
根据unicode
进行拆分:rune
函数。s1 := []rune(s)
-
排序和查找操作
排序操作主要都在
sort
包中,导入就可以使用了。import "sort"
sort.Ints()
对整数进行排序。sort.Strings()
对字符串进行排序。sort.Float64s()
对浮点数进行排序。sort.SearchInts(a []int, x int)
从数组a
中查找x
,其中a
必须是有序的。sort.SearchStrings(a []string, x string)
从数组a
中查找x
,其中a
必须是有序的。sort.SearchFloat64s(a []float64, x float64)
从数组a
中查找x
,其中a
必须是有序的。
map 数据结构
-
map 简介
key-value 的数据结构,又叫字典或关联数组。
-
声明
var map1 map[string]int var map1 map[string]string var map1 map[int]string var map1 map[string]map[string]int
声明是不会分配内存的,需要使用
make
进行初始化。var map1 map[string]int map1 = make(map[string]int) map1 = make(map[string]int, 10) // 第二个参数数字是 map 的容量
也可以在声明的时候直接初始化。
var map1 map[string]int = map[string]int{ "hello": 1, }
map
中后面的值类型也可以是一个map
package main import "fmt" func main() { map1 := make(map[string]map[string]string) map1["key1"] = make(map[string]string) map1["key1"]["key2"] = "hello" map1["key1"]["key3"] = "world" fmt.Println(map1) }
-
-
map
相关操作 -
map
是引用类型 -
slice of map
-
map
排序- 先获取所有的 key,把 key 进行排序
- 按照排好序的 key 进行遍历
- map 中的 key 是无序的
-
map 反转
- 初始化另外一个 map,把 key、value 互换即可。
包
-
golang中的包
- golang目前有150个标准的包,覆盖了几乎所有的基础库
- golang.org有所有包的文档
-
线程同步
import ("sync")
- 互斥锁
var mu sync.Mutex
- 读写锁
var mu sync.RWMutex
-
go get 安装第三方包
go get github.com/go-sql-driver/mysql