Go语言入门练习:Maps 实现单词计数(WordCount)
作为Go语言入门的基础练习,Maps(映射)的使用是重点知识点之一,而单词计数(WordCount)练习则是巩固Maps用法的经典案例。本文将详细记录该练习的实现过程、核心思路、代码解析,以及练习中涉及的关键知识点,适合和我一样正在自学Go语言的参考,也作为自己的学习记录存档。
一、练习需求说明
本次练习的核心需求是实现一个名为WordCount的函数,该函数接收一个字符串参数s,返回一个map[string]int类型的值,其中key是字符串中的每个“单词”,value是该单词在字符串中出现的次数。
练习提供了基础代码框架,同时提示可以使用strings.Fields函数辅助实现,最终通过wc.Test函数运行测试套件,验证函数实现的正确性。
初始基础代码如下:
package main
import (
"golang.org/x/tour/wc"
)
func WordCount(s string) map[string]int {
return map[string]int{"x": 1} // 占位代码,需完善
}
func main() {
wc.Test(WordCount)
}
二、核心思路梳理
要实现单词计数,核心需要完成3个步骤,思路清晰且贴合Go语言的特性:
- 创建一个空的映射(map),用于存储单词和对应的计数,map的键为string类型(单词),值为int类型(计数);
- 将输入的字符串按“单词”分割,这里借助strings.Fields函数,自动处理空白字符(空格、制表符、换行符等),分割后得到单词切片;
- 遍历单词切片,对每个单词进行计数,每遇到一次该单词,就将map中对应的值加1,最终返回这个映射。
三、完善后的完整代码
结合上述思路,完善后的代码如下,关键步骤已添加注释,便于理解:
package main
import (
"strings" // 导入 strings 包,使用 Fields 函数分割单词
"golang.org/x/tour/wc"
)
// WordCount 统计字符串中每个单词的出现次数
func WordCount(s string) map[string]int {
// 1. 创建一个空的 map,用于存储单词和对应的计数
wordMap := make(map[string]int)
// 2. 使用 strings.Fields 分割字符串,按空格/制表符/换行符分割成单词切片
words := strings.Fields(s)
// 3. 遍历单词切片,统计每个单词的数量
for _, word := range words {
wordMap[word]++ // 单词每出现一次,对应计数 +1
}
// 4. 返回统计结果
return wordMap
}
func main() {
// 运行测试函数,验证 WordCount 是否正确
wc.Test(WordCount)
}
四、关键知识点解析
本次练习重点考察Go语言中Maps的使用,同时涉及strings包的基础用法,以下是核心知识点的详细解析,帮助加深理解:
- Maps 的初始化与使用
Go语言中,map的初始化有两种方式:一种是直接使用map字面量(如初始代码中的map[string]int{“x”: 1}),适合已知初始键值对的场景;另一种是使用make函数(make(map[string]int)),适合初始为空、后续动态添加键值对的场景,也是本次练习的首选方式。
特别注意:当访问map中不存在的键时,不会报错,会返回该值类型的默认值(int类型默认值为0),这也是我们能够直接使用wordMap[word]++的原因——第一次遇到某个单词时,其对应的值为0,++后变为1,后续再次遇到则依次累加。 - strings.Fields 函数的作用
strings.Fields函数是Go语言标准库中strings包的常用函数,其作用是将字符串按“空白字符”分割,返回一个字符串切片([]string)。这里的空白字符包括空格、制表符(\t)、换行符(\n)等,并且会自动忽略连续的空白字符,无需我们手动处理多余空格,极大简化了单词分割的逻辑。
举个例子:若输入字符串为”hello world go”(world和go之间有两个空格),strings.Fields处理后得到的切片是[“hello”, “world”, “go”],自动过滤了多余的空格,非常适合单词计数场景。 - 循环遍历切片
本次练习中使用for range循环遍历单词切片,for range循环是Go语言中遍历切片、map等集合的常用方式,语法为for 索引, 值 := range 集合。这里我们只需要用到切片中的“值”(即单词),所以将索引用下划线(_)忽略,避免未使用变量的编译错误。
五、测试结果与验证
完善代码后,运行程序,wc.Test函数会自动执行一系列测试用例,验证WordCount函数的正确性。如果实现正确,控制台会输出“PASS”,表示所有测试用例都通过;若存在错误,则会输出具体的错误信息,提示哪个测试用例未通过,便于我们排查问题。
比如,当输入字符串为”I am learning Go Go”时,函数应返回map[string]int{“I”:1, “am”:1, “learning”:1, “Go”:2},测试套件会自动验证该结果是否正确。如图1

/app/go-tour # cd exercise-maps/
/app/go-tour/exercise-maps # go run main.go
PASS
f("I am learning Go!") =
map[string]int{"Go!":1, "I":1, "am":1, "learning":1}
PASS
f("The quick brown fox jumped over the lazy dog.") =
map[string]int{"The":1, "brown":1, "dog.":1, "fox":1, "jumped":1, "lazy":1, "over":1, "quick":1, "the":1}
PASS
f("I ate a donut. Then I ate another donut.") =
map[string]int{"I":2, "Then":1, "a":1, "another":1, "ate":2, "donut.":2}
PASS
f("A man a plan a canal panama.") =
map[string]int{"A":1, "a":2, "canal":1, "man":1, "panama.":1, "plan":1}
六、学习心得
这个练习看似简单,却覆盖了Go语言中Maps的核心用法、strings包的基础函数以及循环遍历的技巧,非常适合入门阶段巩固知识点。
对于刚开始自学Go语言的我来说,通过这个练习,不仅掌握了map的初始化、键值对的添加和修改,还学会了借助标准库函数简化开发流程——不需要自己手动分割字符串、处理空白字符,体现了Go语言“简洁、高效”的设计理念。
另外,通过编写注释、梳理思路,也加深了对代码的理解,后续遇到类似的计数场景(如统计字符出现次数),也能快速复用本次练习的思路。
七、拓展思考
如果想进一步拓展这个练习,可以尝试以下需求,巩固更多知识点:
- 忽略大小写统计:比如将“Go”和“go”视为同一个单词,可通过strings.ToLower或strings.ToUpper函数将单词统一转为小写或大写后再计数;
- 处理标点符号:比如字符串中包含“hello,”“world!”,需要去除标点符号后再统计单词;
- 统计最长单词:在计数的同时,记录出现次数最多的单词和其出现次数。