什么是 map?
Map 是一种无序的键值对的集合。Map 最重要的一点是通过 key 来快速检索数据,key 类似于索引,指向数据的值。
Map 是一种集合,所以我们可以像迭代数组和切片那样迭代它。不过,Map 是无序的,我们无法决定它的返回顺序,这是因为 Map 是使用 hash 表来实现的。
如何创建 map?
有两种创建map的方式:一是通过字面值;二是通过make函数
/* 声明变量,默认 map 是 nil,如果不初始化 map,那么就会创建一个 nil map。nil map 不能用来存放键值对 */ var variable map[KeyType]ValueType /* 使用字面值 创建和初始化 */ variable := map[KeyType]ValueType{Key1:Value1, Key2:Value2, Keyn:Valuen} /* 使用 make 函数创建和初始化 */ variable := make(map[KeyType]ValueType)
实例DEMO:
向 map 中插入元素
下面的代码插入一些新的元素给 map: userinfo
package main import ( "fmt" ) func main() { /*使用 make 函数创建和初始化 */ userinfo := make(map[string]string) userinfo[ "name" ] = "张三" userinfo[ "age" ] = "18" userinfo[ "phone" ] = "15012341234" userinfo[ "email " ] = "haha@qq.com" fmt.Println(userinfo) //Output: map[age:18 email :haha@qq.com name:张三 phone:15012341234] }
也可以在声明时初始化一个map:
package main import "fmt" func main() { /*使用字面值 创建和初始化map*/ exam := map[string]int{"Math":78, "Chinese":90, "English": 56, "History":61} exam["Music"] = 70 exam["Art"] = 80 fmt.Println(exam) //Output: map[Art:80 Chinese:90 English:56 History:61 Math:78 Music:70] }
string 并不是可以作为键的唯一类型,其他所有可以比较的类型,比如,布尔类型,整型,浮点型,复数类型都可以作为键。如果你想了解更多关于可比较类型的话,请参阅:http://golang.org/ref/spec#Comparison_operators
访问 map 中的元素
现在我们已经添加了一些元素给 map,现在让我们学习如何从 map 中提取它们。根据键获取值的语法为:map[key],例如:
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 employee := "jamie" fmt.Println("Salary of", employee, "is", personSalary[employee]) //Output: Salary of jamie is 15000 }
如果一个键不存在会发生什么?map 会返回值类型的默认值。比如如果访问了 personSalary 中的不存在的键,那么将返回 int 的默认值:0
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 employee := "jamie" fmt.Println("Salary of", employee, "is", personSalary[employee]) fmt.Println("Salary of joe is", personSalary["joe"]) //Output: // Salary of jamie is 15000 // Salary of joe is 0 }
检测一个键是否存在于一个 map 中?可以使用下面的语法:
value, ok := map[key]
上面的语法可以检测一个特定的键是否存在于 map 中。如果 ok 是 true,则键存在,value 被赋值为对应的值。 如果 ok为 false,则表示键不存在。
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 newEmp := "joe" value, ok := personSalary[newEmp] if ok == true { fmt.Println("Salary of", newEmp, "is", value) } else { fmt.Println(newEmp,"not found") } //Output: joe not found }
遍历 map 中的元素
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 for key, value := range personSalary { fmt.Printf("personSalary[%s] = %d\n", key, value) } //Output: //personSalary[jamie] = 15000 //personSalary[mike] = 9000 //personSalary[steve] = 12000 }
因为 map 是无序的,因此对于程序的每次执行,不能保证使用for range 遍历 map 的顺序总是一致的。
删除元素
delete(map, key) //用于删除 map 中的 key。delete 函数没有返回值。
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 fmt.Println("map before deletion", personSalary) delete(personSalary, "steve") fmt.Println("map after deletion", personSalary) //Output: //map before deletion map[jamie:15000 mike:9000 steve:12000] //map after deletion map[jamie:15000 mike:9000] }
获取map 大小
用内置函数 len 获取 map 的大小:
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 fmt.Println("length is", len(personSalary)) //Output: length is 3 }
map 是引用类型
与切片一样,map 是引用类型。当一个 map 赋值给一个新的变量,它们都指向同一个内部数据结构。因此改变其中一个也会反映到另一个:
package main import ( "fmt" ) func main() { personSalary := map[string]int{ "steve": 12000, "jamie": 15000, } personSalary["mike"] = 9000 fmt.Println("Original person salary", personSalary) newPersonSalary := personSalary newPersonSalary["mike"] = 18000 fmt.Println("Person salary changed", personSalary) //Output //Original person salary map[jamie:15000 mike:9000 steve:12000] //Person salary changed map[jamie:15000 mike:18000 steve:12000] }
将 map 作为参数传递给函数也是一样的。在函数中对 map 的任何修改都会影响在调用函数中看到。