字典是一组`无序的`,`键值对`的`集合`。
字典也叫做`关联数组`,因为数组通过`索引`来查找元素,而字典通过`键`来查找元素。当然,很显然的,字典的键是不能重复的。如果试图赋值给同一个键,后赋值的值将覆盖前面赋值的值。
字典的定义也有两种,一种是`初始化数据`的定义方式,另一种是`使用神奇的make函数`来定义。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 var x = map[string]string{ 9 "A": "Apple", 10 "B": "Banana", 11 "O": "Orange", 12 "P": "Pear", 13 } 14 15 for key, val := range x { 16 fmt.Println("Key:", key, "Value:", val) 17 } 18 }
输出结果为
Key: A Value: Apple
Key: B Value: Banana
Key: O Value: Orange
Key: P Value: Pear
在上面的例子中,我们定义了一个string:string的字典,其中`[]`之间的是键类型,右边的是值类型。另外我们还看到了`range函数,此函数一样神奇,可以用来迭代字典元素,返回key:value键值对`。当然如果你对键或者值不感兴趣,一样可以使用`下划线(_)`来忽略返回值。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 var x map[string]string 9 10 x = make(map[string]string) 11 12 x["A"] = "Apple" 13 x["B"] = "Banana" 14 x["O"] = "Orange" 15 x["P"] = "Pear" 16 17 for key, val := range x { 18 fmt.Println("Key:", key, "Value:", val) 19 } 20 }
上面的方式就是使用了make函数来初始化字典,`试图为未经过初始化的字典添加元素会导致运行错误`,你可以把使用make函数初始化的那一行注释掉,然后看一下。
当然上面的例子中,我们可以把定义和初始化合成一句。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 x := make(map[string]string) 9 10 x["A"] = "Apple" 11 x["B"] = "Banana" 12 x["O"] = "Orange" 13 x["P"] = "Pear" 14 15 for key, val := range x { 16 fmt.Println("Key:", key, "Value:", val) 17 } 18 }
现在我们再来看一下字典的数据访问方式。如果你访问的元素所对应的键存在于字典中,那么没有问题,如果不存在呢?
这个时候会返回零值。对于字符串零值就是"",对于整数零值就是0。但是对于下面的例子:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 x := make(map[string]int) 9 10 x["A"] = 0 11 x["B"] = 20 12 x["O"] = 30 13 x["P"] = 40 14 15 fmt.Println(x["C"]) 16 }
在这个例子中,很显然不存在键C,但是程序的输出结果为0,这样就和键A对应的值混淆了。
Go提供了一种方法来解决这个问题:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 x := make(map[string]int) 9 10 x["A"] = 0 11 x["B"] = 20 12 x["O"] = 30 13 x["P"] = 40 14 15 if val, ok := x["C"]; ok { 16 fmt.Println(val) 17 } 18 }
上面的例子中,我们可以看到事实上使用`x["C"]`的返回值有两个,一个是值,另一个是是否存在此键的bool型变量,所以我们看到ok为true的时候就输出键C的值,如果ok为false,那就是字典中不存在这个键。
现在我们再来看看`Go提供的内置函数delete,这个函数可以用来从字典中删除元素`。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 x := make(map[string]int) 9 10 x["A"] = 10 11 x["B"] = 20 12 x["C"] = 30 13 x["D"] = 40 14 15 fmt.Println("Before Delete") 16 fmt.Println("Length:", len(x)) 17 fmt.Println(x) 18 19 delete(x, "A") 20 21 fmt.Println("After Delete") 22 fmt.Println("Length:", len(x)) 23 fmt.Println(x) 24 }
输出结果为
Before Delete
Length: 4
map[A:10 B:20 C:30 D:40]
After Delete
Length: 3
map[B:20 C:30 D:40]
我们在删除元素前查看一下字典长度和元素,删除之后再看一下。这里面我们还可以看到`len函数也可以用来获取字典的元素个数`。当然如果你试图删除一个不存在的键,那么程序也不会报错,只是不会对字典造成任何影响。
最后我们再用一个稍微复杂的例子来结束字典的介绍。
我们有一个学生登记表,登记表里面有一组学号,每个学号对应一个学生,每个学生有名字和年龄。
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 var facebook = make(map[string]map[string]int) 9 facebook["0616020432"] = map[string]int{"Jemy": 25} 10 facebook["0616020433"] = map[string]int{"Andy": 23} 11 facebook["0616020434"] = map[string]int{"Bill": 22} 12 13 for stu_no, stu_info := range facebook { 14 fmt.Println("Student:", stu_no) 15 for name, age := range stu_info { 16 fmt.Println("Name:", name, "Age:", age) 17 } 18 fmt.Println() 19 } 20 }
输出结果为
Student: 0616020432
Name Jemy Age 25
Student: 0616020433
Name Andy Age 23
Student: 0616020434
Name Bill Age 22
当然我们也可以用初始化的方式定义字典:
1 package main 2 3 import ( 4 "fmt" 5 ) 6 7 func main() { 8 var facebook = map[string]map[string]int{ 9 "0616020432": {"Jemy": 25}, 10 "0616020433": {"Andy": 23}, 11 "0616020434": {"Bill": 22}, 12 } 13 14 for stu_no, stu_info := range facebook { 15 fmt.Println("Student:", stu_no) 16 for name, age := range stu_info { 17 fmt.Println("Name:", name, "Age:", age) 18 } 19 fmt.Println() 20 } 21 }
输出结果是一样的。