map
在 C++/java中,map一般都以库的方式提供,比如在 C++中是 STL的 std::map<>,在 C#中是 Dictionary<>,在java中 HashMAP<>,在这些语言中,如果要使用 map就必须要先引入相应的库,而在 go 中,则不需要引入任何库,适用也比较方便
map是一堆键值对的未排序集合,比如一身份证作为唯一键来表示一个人的信息,则这个 map 可以定义成这个样子:
func main() {
//personDB 是声明的map变量名,string是键的类型,PersonInfo则是存放的类型
var personDB map[string] PersonInfo
//这里我们使用 make() 内置函数创建了一个新的 map() 下面是指创建了一个键类型为 string,值类型为 PersonInfo 的 map
personDB = make(map[string] PersonInfo)
//添加信息
personDB["412725"] = PersonInfo{"123","zhangsan","beijing"}
personDB["412725333"] = PersonInfo{"123","lisi","nanjing"}
//判断是否存在键为 412725 如果存在 ok 的值为 true 不存在则反之
person, ok := personDB["412725"]
if ok {
fmt.Println("this here",person)
//从 PersonDB 中删除这个键为 412725 的元素,加入这个键并不存在,那么这个调用什么都不会发生,也不会存在什么副作用
//如果我们传入的 map 变量的值为 nil 则会抛出一个异常
delete(personDB, "412725")
}else {
fmt.Println("is not here")
}
for i, v := range personDB {
fmt.Println("键是:",i,"/t对应的值是:",v)
}
}
输出信息:
this here {123 zhangsan beijing}
键是: 412725333 /t对应的值是: {123 lisi nanjing}
从最后我们的变量可以看出 map中是存在:412725 这个键的,这个时候 ok 的值为 true,走进 if 里,执行了 delete(),最后我们的打印可以看出,这个元素已经被成功删除!
这里多说一点,另一种创建 map 直接初始化的方法,如下:
myMap = map[string] PersonInfo{
"1234": PersonInfo{"1", "Jack", "Room 101,..."},
...
...
...
}
map中的元素查找
go语言中,map的查找功能设计的比较精巧,其他语言中,加入我们判断能否获取到一个值不是一件容易的事情,判断能否从 map 中获取一个值的常规做法是:
- 声明并且初始化一个变量为空
- 试图从 map 中获取对应的键的值到该变量中
- 判断该变量是否为空,如果为空,则表示 map 中不存在该变量
这种用法比较啰唆,而且判断变量是否为空这条语句并不能真正表意(是否成功取到对应的
值),从而影响代码的可读性和可维护性。有些库甚至会设计为因为一个键不存在而抛出异常,
让开发者用起来胆战心惊,不得不一层层嵌套try-catch语句,这更是不人性化的设计。在Go
语言中,要从map中查找一个特定的键,可以通过下面的代码来实现:
value, ok := myMap["1234"]
if ok { // 找到了
// 处理找到的value
}
判断是否成功找到特定的键,不需要检查取到的值是否为nil,只需查看第二个返回值ok,
这让表意清晰很多。配合:=操作符,让你的代码没有多余成分,看起来非常清晰易懂