map的介绍
map是key-value数据结构,又称为字段或者关联数组。在编程中经常使用到
map的声明
基本语法
var map 变量名 map[keytype]valuetype
key可以是什么类型
var a map[string]string var a map[string]int var a map[int]string var a map[string]map[string]string
package main import "fmt" func main() { var a map[string]string // 在使用map前,需要先make,make的作用就是给map分配数据空间 a = make(map[string]string,10) a["name1"]="bingle1" a["name2"]="bingle2" a["name3"]="bingle3" a["name4"]="bingle4" fmt.Println(a) }
执行结果为:
map[name1:bingle1 name2:bingle2 name3:bingle3 name4:bingle4]
对上面代码的说明:
1、map 在使用前一定要 make
2、map 的 key 是不能重复,如果重复了,则以最后这个 key-value 为准
3、map 的 value 是可以相同的.
4、map 的 key-value 是无序、
5、make 内置函数数目
内建函数make分配并初始化一个类型为切片、映射、或通道的对象。其实第一个实参为类型,而非值。make的返回类型与其参数相同,而非指向它的指针,其具体结果取决于具体的类型:
切片:size指定了其长度,该切片的容量等于其长度。切片支持第二个整数实参可用来指定不同的容量;它必须不小于其长度,因此make([]int 0, 10)会分配一个长度为0,容量为10的切片。
map的使用
方式1:
package main import "fmt" func main() { var a map[string]string // 在使用map前,需要先make,make的作用就是给map分配数据空间 a = make(map[string]string,10) a["name1"] = "bingle1" a["name2"] = "bingle2" a["name3"] = "bingle3" a["name4"] = "bingle4" fmt.Println(a) }
方式 2:
package main import "fmt" func main() { names :=make(map[string]string) names["name1"] ="bingle1" names["name2"] ="bingle2" names["name3"] ="bingle3" names["name4"] ="bingle4" fmt.Println(names) }
方式 3:
package main import "fmt" func main() { names := map[string]string{ "name1": "bingle1", "name2": "bingle2", "name3": "bingle3", "name4": "bingle4", } names["name2"] = "bingle222222" fmt.Println("names = ", names) }
map的增删改查操作
1、map的增加和更新:
内建函数delete按照指定的键将元素从映射中删除,若 m 为 nil 或者 无此元素,delete不进行操作.
package main import "fmt" func main() { names := map[string]string{ "name1": "bingle1", "name2": "bingle2", "name3": "bingle3", "name4": "bingle4", } delete(names,"name1") fmt.Println("names = ", names) }
细节说明:
如果我们要删除 map 的所有 key ,没有一个专门的方法一次删除,可以遍历一下 key, 逐个删除或者 map = make(...),make 一个新的,让原来的成为垃圾,被 gc 回收
package main import "fmt" func main() { names := map[string]string{ "name1": "bingle1", "name2": "bingle2", "name3": "bingle3", "name4": "bingle4", } names = make(map[string]string) fmt.Println("names = ", names) }
3、map查找
package main import "fmt" func main() { names := map[string]string{ "name1": "bingle1", "name2": "bingle2", "name3": "bingle3", "name4": "bingle4", } val1,ok1 := names["name1"] val2,ok2 := names["name1111"] if ok1 { fmt.Printf("有name1 key 值为 %v ",val1) }else { fmt.Printf("没有name1 key值") } if ok2 { fmt.Printf("有name2 key 值为 %v ",val2) }else { fmt.Printf("没有name2 key值") } }
对上面代码说明:说明:如果 heroes 这个 map 中存在 "no1" , 那么 findRes 就会返回 true,否则返回 false
map遍历
package main import "fmt" func main() { names := map[string]string{ "name1": "bingle1", "name2": "bingle2", "name3": "bingle3", "name4": "bingle4", } for k, v := range names { fmt.Printf("k = %v ,v = %v ", k, v) } }
map的长度
内置 len 返回 v 的长度,这取决于具体类型:
数组:v 中元素的数量
数组指针:*v 中元素的数量(v 为 nil 的时候panic)
切片、映射:v 中元素的数量,若 v 为 nil ,len(v) 为零
字符串:v 中字节的数量
通道:通道缓存中队列(未读取)元素的数量,若 v 为 nil ,len(v) 为零
package main import "fmt" func main() { names := map[string]string{ "name1": "bingle1", "name2": "bingle2", "name3": "bingle3", "name4": "bingle4", } fmt.Println(len(names)) }
map切片
基本介绍:
切片的数据类型如果是 map,则我们称为 slice of map,map 切片,这样使用则 map 个数就可以动态变化了。
案例:
要求:使用一个 map 来记录 monster 的信息 name 和 age, 也就是说一个 monster 对应一个 map,并且妖怪的个数可以动态的增加
package main import ( "fmt" ) func main() { //1. 声明一个map切片 var monsters []map[string]string monsters = make([]map[string]string, 2) //准备放入两个妖怪 //2. 增加第一个妖怪的信息 if monsters[0] == nil { monsters[0] = make(map[string]string, 2) monsters[0]["name"] = "牛魔王" monsters[0]["age"] = "500" } if monsters[1] == nil { monsters[1] = make(map[string]string, 2) monsters[1]["name"] = "玉兔精" monsters[1]["age"] = "400" } // 下面这个写法越界。 // if monsters[2] == nil { // monsters[2] = make(map[string]string, 2) // monsters[2]["name"] = "狐狸精" // monsters[2]["age"] = "300" // } //这里我们需要使用到切片的append函数,可以动态的增加monster //1. 先定义个monster信息 newMonster := map[string]string{ "name" : "新的妖怪~火云邪神", "age" : "200", } monsters = append(monsters, newMonster) fmt.Println(monsters) }
map 排序
基本介绍:
1、golang 中没有一个专门的方法针对 map 的 key 进行排序
2、golang 中的 map 默认是无序的,注意也不是按照添加的顺序存放的,你每次遍历,得到的输出可能不一样.
3、golang 中 map 的排序,是先将 key 进行排序,然后根据 key 值遍历输出即可
代码如下:
package main import ( "fmt" "math/rand" "sort" "time" ) func main() { rand.Seed(time.Now().UnixNano()) //初始化随机数种子 var scoreMap = make(map[string]int, 200) for i := 0; i < 100; i++ { key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串 value := rand.Intn(100) //生成0~99的随机整数 scoreMap[key] = value } //取出map中的所有key存入切片keys var keys = make([]string, 0, 200) for key := range scoreMap { keys = append(keys, key) } //对切片进行排序 sort.Strings(keys) //按照排序后的key遍历map for _, key := range keys { fmt.Println(key, scoreMap[key]) } }
map 使用细节
1、map 是引用类型,遵守引用类型传递的机制,在一个函数接收 map,修改后,会直接修改原来的 map
package main import ( "fmt" "math/rand" "sort" "time" ) func modify(scoreMap map[string]int) { scoreMap["stu01"] = 999 } func main() { rand.Seed(time.Now().UnixNano()) //初始化随机数种子 var scoreMap = make(map[string]int, 200) for i := 0; i < 100; i++ { key := fmt.Sprintf("stu%02d", i) //生成stu开头的字符串 value := rand.Intn(100) //生成0~99的随机整数 scoreMap[key] = value } //取出map中的所有key存入切片keys var keys = make([]string, 0, 200) for key := range scoreMap { keys = append(keys, key) } //对切片进行排序 sort.Strings(keys) //按照排序后的key遍历map for _, key := range keys { fmt.Println(key, scoreMap[key]) } fmt.Println("==============") modify(scoreMap) for _, key := range keys { fmt.Println(key, scoreMap[key]) } }
2、map 的容量达到后,再想 map 增加元素,会自动扩容,并不会发生 panic,也就是说 map 能动态的增长 键值对(key-value)
3、map 的 value 也经常使用 struct 类型,更适合管理复杂的数据(比前面 value 是一个 map 更好)
比如 value 为 Student 结构体
package main import "fmt" // 定义一个学生结构体 type Student struct { Name string Age int Address string } func main() { students := make(map[string]Student,10) stu1 := Student{"bingel1", 18, "北京"} stu2 := Student{"bingel2", 28, "上海"} students["stu1"] = stu1 students["stu2"] = stu2 fmt.Println(students) //遍历各个学生信息 for k, v := range students { fmt.Printf("学生的编号是%v ", k) fmt.Printf("学生的名字是%v ", v.Name) fmt.Printf("学生的年龄是%v ", v.Age) fmt.Printf("学生的地址是%v ", v.Address) fmt.Println() } }