go语言基础变量类型 变量定义 1 2 3 4 5 var a int /float32 /float64 /string /bool /... = valuevar b := value var c [3 ][4 ] int interface {}
nil nil 是一个预先声明的标识符,指针、通道、函数、接口、map、切片的零值就是nil
nil 是没有默认类型的,他的类型具有不确定性,我们在使用它时必须要提供足够的信息能够让编译器推断 nil 期望的类型
以下是 nil 的一些注意事项: 1. 声明一个 nil 的 map,map 可以读数据,但是不能写数据 2. 关闭一个 nil 的 channel 会引发 panic 3. nil切片不能进行索引访问,会引发 panic 4. 方法接收者为 nil 时,如果在方法内使用到了会引发 panic 5. 空指针一个没有任何值的指针
切片(变长数组) 切片的声明 1 2 3 4 5 6 7 8 9 10 11 12 13 14 var s1 []int s2 := []int {} var s3 []int = make ([]int , 0 , 0 ) arr := [5 ]int {1 , 2 , 3 , 4 , 5 } var s6 []int s6 = arr[1 :4 ] s7 = arr[:3 :8 ] s8 [][]int { []int {1 , 2 , 3 }, []int {100 , 200 }, []int {11 , 22 , 33 , 44 }, }
切片的读写 1 2 3 data := [...]int {0 , 1 , 2 , 3 , 4 , 5 } s := data[2 :4 ] s[0 ] += 100
结果是 data 的数据改变了。切片的一切修改都是在底层数组上的修改( make 创建的切片会自动分配一个数组)
切片的函数 append/copy 1 2 3 4 5 var a = []int {1 , 2 , 3 }b := append (a,4 ) c := make ([]int ,3 ) copy (c,a) d := a
切片/数组遍历 range 1 2 3 4 5 data := [...]int {0 , 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 } slice := data[:] for index, value := range slice { fmt.Printf(index, value) }
map map 声明 1 2 map [KeyType]ValueTypemake (map [KeyType]ValueType, 0 )
map的增删改查 1 2 3 4 5 6 a := make (map [string ]int , 8 ) a["DLUT" ] = 985 a["DLUT-开发区" ] = 985 a["DLUT-开发区" ] = 211 delete (a,"DLUT-开发区" ) v,ok = a["DLUT" ]
map的遍历 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 scoreMap := make (map [string ]int ) scoreMap["张三" ] = 90 scoreMap["小明" ] = 100 scoreMap["娜扎" ] = 60 for k, v := range scoreMap { fmt.Println(k, v) } var keys = make ([]string , 0 , 200 )for key := range scoreMap { keys = append (keys, key) } for _, key := range keys { fmt.Println(key, scoreMap[key]) }
map的拷贝 1 2 3 4 5 6 mapp := map [string ]int { "steve" : 12000 , "jamie" : 15000 , } newmapp := mapp newmapp["steve" ] = 18000
sync.Map Go语言中的 map 在并发情况下,只读是线程安全的,同时读写是线程不安全的。
需要并发读写时,一般的做法是加锁,但这样性能并不高,Go语言在 1.9 版本中提供了一种效率较高的并发安全的 sync.Map,sync.Map 和 map 不同,不是以语言原生形态提供,而是在 sync 包下的特殊结构。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 syncmap.Store("zhangsan" , 97 ) syncmap.Store("lisi" , 100 ) syncmap.Store("wangmazi" , 200 ) v, ok := syncmap.LoadOrStore(3 , "three" ) fmt.Println(v, ok) v, ok = syncmap.LoadOrStore(1 , "thisOne" ) fmt.Println(v, ok) fmt.Println(syncmap.Load("lisi" )) syncmap.Delete("lisi" ) var syncmap sync.Map v, ok := syncmap.LoadAndDelete("xiaomi" ) fmt.Println(v, ok) syncmap.Store("xiaomi" , "xiaomi" ) v, ok = syncmap.LoadAndDelete("xiaomi" ) fmt.Println(v, ok) syncmap.Range(func (k, v interface {}) bool { fmt.Println(k, v) return true })
结构体 结构体的声明 1 2 3 4 5 6 7 8 9 10 11 12 type MyStruct struct { Name string Age int } func (test MyStruct) test() (){ } func (test *MyStruct) test() (){ }
结构体的实例化与初始化 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 type test struct { Name string Age int } t1 := test{"Alice" , 30 } t2 := test{Name: "Alice" } t3 := new (test) (*t3).Name="123" var t4 testt4.Name = "123" var t5 = &test{}
结构体匿名字段 结构体允许其成员字段在申明的时候没有字段名只有字段类型,这种没有名字的字段就称为匿名字段
匿名字段并不是说没有字段名,而是默认会采用类型名作为字段名
结构体要求字段名唯一,因此一个结构体中同种类型的匿名字段只能有一个
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 type Person struct { string int } person := Person{ "GGBond" , 18 , } type Animal struct { name string } type Dog struct { Feet int8 *Animal }
结构体的JSON序列化与tag 1 2 3 4 5 6 7 8 9 10 type userInfo struct { Name string Age int `json:"age"` Hobby []string } a := userInfo{Name: "wang" , Age: 18 , Hobby: []string {"Golang" , "TypeScript" }} buf, err := json.Marshal(a) var b userInfoerr = json.Unmarshal(buf, &b)
结构体的拷贝问题 1 2 3 4 5 6 7 8 9 type Person struct { name string age int8 dreams []string } func (p *Person) SetDreams(dreams []string ) { p.dreams = make ([]string , len (dreams)) copy (p.dreams, dreams) }
拷贝 值类型的数据,默认全部都是深复制,Array、Int、String、Struct、Float,Bool。
引用类型的数据,默认全部都是浅复制,Slice,Map。
深拷贝 对于值类型的数据可以直接使用=进行深拷贝
切片 使用 copy() 函数进行深拷贝
1 2 3 4 5 6 7 8 9 10 matA := [][]int { {0 , 1 , 1 , 0 }, {0 , 1 , 1 , 1 }, {1 , 1 , 1 , 0 }, } matB := make ([][]int , len (matA)) for i := range matA { matB[i] = make ([]int , len (matA[i])) copy (matB[i], matA[i]) }
map 手写函数实现深拷贝
1 2 3 4 newMap := make (map [string ]int ) for k, v := range Map { newMap[k] = v }
浅拷贝 不赘述