前言
在数组这一章节中,我们学会了如何按顺序存储值。现在,我们再来看看如何通过
键
存储值,并快速查找它们。Maps 允许你以类似于字典的方式存储值。你可以将
键
视为单词,将值视为定义。
所以,难道还有比构建我们自己的字典更好的学习 map 的方式吗?
正文
首先编写测试
在 dictionary_test.go
中编写代码:
package main import "testing" func TestSearch(t *testing.T) { dictionary := map[string]string{"test": "this is just a test"} got := Search(dictionary, "test") want := "this is just a test" if got != want { t.Errorf("got '%s' want '%s' given, '%s'", got, want, "test") } }
声明 map 的方式有点儿类似于数组。
不同之处是,它以
map
关键字开头,需要两种类型。第一个是键的类型,写在 []
中。第二个是值的类型,跟在 []
之后。键的类型很特别,它只能是一个可比较的类型,因为如果不能判断两个键是否相等,我们就无法确保我们得到的是正确的值。可比类型在语言规范中有详细解释。
另一方面,值的类型可以是任意类型,它甚至可以是另一个 map。
尝试运行测试
运行 go test
后编译器会提示失败信息 ./dictionary_test.go:8:9: undefined: Search
。
编写最少量的代码让测试运行并检查输出
在 dictionary.go
中:
package main func Search(dictionary map[string]string, word string) string { return "" }
测试应该失败并显示明确的错误信息:
dictionary_test.go:12: got '' want 'this is just a test' given, 'test'
编写足够的代码使测试通过
func Search(dictionary map[string]string, word string) string { return dictionary[word] }
从 map 中获取值和数组相同,都是通过 map[key]
的方式。
重构
func TestSearch(t *testing.T) { dictionary := map[string]string{"test": "this is just a test"} got := Search(dictionary, "test") want := "this is just a test" assertStrings(t, got, want) } func assertStrings(t *testing.T, got, want string) { t.Helper() if got != want { t.Errorf("got '%s' want '%s'", got, want) } }
创建一个 assertStrings
辅助函数并删除 given
的部分让实现更通用。
使用自定义的类型
我们可以通过为 map 创建新的类型并使用 Search
方法改进字典的使用。
在 dictionary_test.go
中:
func TestSearch(t *testing.T) { dictionary := Dictionary{"test": "this is just a test"} got := dictionary.Search("test") want := "this is just a test" assertStrings(t, got, want) }
我们已经开始使用
Dictionary
类型了,但是我们还没有定义它。然后要在 Dictionary
实例上调用 Search
方法。我们不需要更改
assertStrings
。
在
dictionary.go
中:
type Dictionary map[string]string func (d Dictionary) Search(word string) string { return d[word] }
在这里,我们创建了一个 Dictionary
类型,它是对 map
的简单封装。定义了自定义类型后,我们可以创建 Search
方法。