以下是对map学习时的笔记以及代码示例,同时对深拷贝和浅拷贝作了补充:
Map:Go语言内置类型,将一个值与一个键联系起来,可以使用相应的键检索值
1.map是无序的,每次打印出来的map都会不一样,不能使用index获取,只能使用key获取
2.map的长度不固定,和slice一样,是引用类型
3.内置的len函数同样可以获取map拥有的key数量
4.map的key是所有可比较的类型,如布尔型,整数型,浮点型。。。
5.和slice一样,默认值都为nil,但是空的map不可以使用,slice可以直接使用
创建map:
1.var map名 map[key类型]值类型,如var a map[int]string,创建的是nil的map,不能直接使用
2.var map名=make(map[key类型]值类型),这样则map不为空
3.var map名=map[key类型]值类型{key:value,key:value,key:value}
package main
import "fmt"
func main() {
a1 := [4]int{1, 2, 3, 4}
a2 := a1 //值传递
a1[0] = 3
fmt.Printf("a1: %v\n", a1)
fmt.Printf("a2: %v\n", a2)
a3 := []int{1, 2, 3, 4} //切片是引用类型传递
a4 := a3 //这样的赋值方式使得,a3或者a4中的任何更改都会使得两个变量同时改变,因为是对同一内存地址的改变
a3[2] = 56
fmt.Printf("a3: %v\n", a3)
fmt.Printf("a4: %v\n", a4)
a4[0] = 5
fmt.Printf("a3: %v\n", a3)
fmt.Printf("a4: %v\n", a4)
a3 = append(a3, 5, 6, 9, 3) //扩容之后地址不变,即切片赋值,仅仅复制了内存地址给原变量
fmt.Printf("a3: %v\n", a3)
fmt.Printf("a4: %v\n", a4)
//深拷贝和浅拷贝:
/*
深拷贝:拷贝的是数据本身(值类型默认都是深拷贝)
浅拷贝:拷贝的是数据地址(引用类型默认都是浅拷贝)
*/
s1 := []int{1, 2, 3, 4}
s2 := make([]int, 0)
for i := 0; i < len(s1); i++ {
s2 = append(s2, s1[i])
}
fmt.Printf("s1: %v\n", s1)
fmt.Printf("s2: %v\n", s2)
s1[0] = 100
fmt.Printf("s1: %v\n", s1)
fmt.Printf("s2: %v\n", s2) //s2中元素没有改变,深拷贝
s3 := s2
fmt.Printf("s3: %p\n", s3)
fmt.Printf("s2: %p\n", s2)
fmt.Printf("s3: %v\n", s3)
copy(s2, s3) //s3拷贝给s2
fmt.Printf("s2: %v\n", s2)
copy(s2, s3[1:])//拷贝一部分
fmt.Printf("s2: %v\n", s2)
}
package main
import "fmt"
func main() {
/*
Map:Go语言内置类型,将一个值与一个键联系起来,可以使用相应的键检索值
1.map是无序的,每次打印出来的map都会不一样,不能使用index获取,只能使用key获取
2.map的长度不固定,和slice一样,是引用类型
3.内置的len函数同样可以获取map拥有的key数量
4.map的key是所有可比较的类型,如布尔型,整数型,浮点型。。。
5.和slice一样,默认值都为nil,但是空的map不可以使用,slice可以直接使用
创建map:
1.var map名 map[key类型]值类型,如var a map[int]string,创建的是nil的map,不能直接使用
2.var map名=make(map[key类型]值类型),这样则map不为空
3.var map名=map[key类型]值类型{key:value,key:value,key:value}
*/
var map1 map[int]string //创建一个空map,不能直接使用
var map2 = make(map[int]string) //最常用的创建形式
var map3 = map[int]string{1: "liu", 2: "yang"} //键不能重复,否则后面的值会覆盖前面的
fmt.Println(map1 == nil)
fmt.Println(map2 == nil)
fmt.Println(map3 == nil)
if map1 == nil {
map1 = make(map[int]string)
}
fmt.Println(map1 == nil) //这样才能使用map1
/*
map的使用:存储键值对到map中
*/
map1[1] = "zhang"
map1[2] = "实际上"
map1[3] = "但是"
fmt.Println(map1)
fmt.Println(map1[2]) //根据key获取对应的value,如果key不存在,则获取的是value值类型的零值
//当key不存在的时候程序不会报错,可以使用value,ok:=map[key],如果ok为true则说明map[key]存在
v1, ok := map1[5]
if ok {
fmt.Println(v1)
}
fmt.Println(map1[6]) //注意是无序的
//修改数据
map1[2] = "计算机"
fmt.Printf("map1: %v\n", map1)
//删除数据,delete(map名,要删除的键)
delete(map1, 2)
fmt.Printf("map1: %v\n", map1)
//获取长度
fmt.Println(len(map1))
//map的遍历
for k, v := range map1 {
fmt.Println(k, v)
}
//或者:
/*
1.获取所有的key,存储到切片或者数组
2.进行排序(sort包),sort.Ints(keys)
3.遍历key
*/
/*
map结合slice
*/
maps := make(map[string]string)
maps["name"] = "刘洋"
maps["age"] = "22"
maps["sex"] = "female"
fmt.Printf(" %v\n", maps)
mapx := make(map[string]string)
mapx["name"] = "张三"
mapx["age"] = "20"
mapx["sex"] = "male"
//存储到slice
s1 := make([]map[string]string, 0)
s1 = append(s1, maps, mapx)
fmt.Printf("s1: %v\n", s1)
for i, v := range s1 {
fmt.Printf("第%d个人的信息是:\n", i+1)
fmt.Printf("\t姓名:%s\n", v["name"])
fmt.Printf("\t年龄:%s\n", v["age"])
fmt.Printf("\t性别:%s\n", v["sex"])
}
//map是引用类型,会传递地址
mapz := make(map[int]string)
mapz[1] = "liuyang"
mapz[2] = "liurui"
mapzzz := make(map[string]map[string]string) //值仍然能是map
m1 := make(map[string]string)
m1["name"] = "jack"
m1["age"] = "20"
m1["salary"] = "20000"
mapzzz["manager"] = m1
m2 := make(map[string]string)
m2["name"] = "ruby"
m2["age"] = "30"
m2["salary"] = "30000"
mapzzz["boss"] = m2
fmt.Printf("mapzzz: %v\n", mapzzz)
m1["name"] = "zhangsan"
m2["name"] = "liuli"
fmt.Printf("mapzzz: %v\n", mapzzz) //mapzzz改变为m1,m2中修改后的值
//总结:使用make函数创建的都是引用类型,是对内存地址进行操作
}