这是我参与第六届字节跳动青训营后端班的第2篇笔记,和上一篇一样,应该很早就发的,是不才拖延症选手拖到现在才整理笔记。此篇笔记梳理Go语言实战部分内容,此部分内容比较多,为避免篇幅过长,第三个例子和课后作业部分内容放到下一篇笔记。
猜谜游戏
课程的第一个例子,使用 Golang 来构建一个猜数字游戏。在这个游戏里面,程序首先会生成一个介于 1 到 100 之间的随机整数,然后提示玩家进行猜测。玩家每次输入一个数字,程序会告诉玩家这个猜测的值是高于还是低于那个秘密的随机数,并且让玩家再次猜测。如果猜对了,就告诉玩家胜利并且退出程序。
可以看到,当程序运行的时候会生成一个 0 到 100 之间的随机数字。
首先来生成这个随机数。生成随机数需要用到 math/rand 包。我们先导入 FMT 包和 math/rand 包,定义一个变量, max_num 是100。根据这个包的文档,我们使用它之前需要设置随机数种子,否则的话每一次都会生成相同的随机数序列。一般惯例用法是在程序启动的时候,用启动的时间戳来初始化随机数种子。然后用 rand.Intn 来生成一个随机数,再打印出这个随机数。
然后需要实现用户输入输出,并解析成数字。我们用reader变量的 ReadString 方法来读取一行输入。读取失败则打印错误并退出。ReadString 返回的结果包含结尾的换行符,我们把它去掉并转换成数字。同样如果转换失败就打印错误、退出。
接下来实现判断逻辑。现在已经有了一个秘密的值,然后也从用户的输入里面读到了一个值,要来比较这两个值的大小。如果是用户输入的值比那个秘密的值要大的话,就告诉用户猜的值太大了,请再试一次。如果是小了也同理,如果是相等的话,就告诉用户赢了。
然后要实现游戏的循环,否则用户只能输入一次猜测,且无论猜测是否正确,程序都会突退出。为了让游戏可以正常玩下去,需要加一个循环。把现有的代码挪到一个 for 循环里面,再把 return 改成 continue 以便于在出错的时候能够继续循环。在用户输入正确的时候 break ,这样就能够在用户胜利的时候退出游戏。
至此,采用Golang实现的猜谜游戏成功构建完成。
在线词典
第二个例子更复杂一点,是一个命令行排版的词典。
用户可以在命令行里面查询一个单词,我们通过调用第三方的 API 查询到单词的翻译并打印出来。这个例子里面,我们会学习如何用 Go 语言来发送 HTTP 请求、解析json,还会学习如何使用代码生成来提高开发效率。
首先是要用到的 API,以彩云科技提供的在线翻译为例。打开彩云翻译的网页,然后右键检查打开浏览器的开发者工具。
然后点一下翻译按钮,浏览器会发送一系列请求,找到那个用来查询单词的请求。这是一个 HTTP 的 post 的请求,API 的返回结果里面会有 Wiki 和 dictionary 两个字段。我们需要用的结果主要在dictionary.Explanations 字段里面。
要在 Golang 里面去发送这个请求,可以用一种非常简单的方式来生成代码,右键浏览器里面的 copy as curl。 copy完成之后在终端粘贴一下 curl 命令,可以成功返回一大串 json。
然后打开这个代码生成网站curlconverter.com/#go ,粘贴 curl 请求,在右边的语言里面选 Golang 就能够看到一串很长的代码,直接把它 copy 到我们的编辑器里面。生成代码有转义导致的编译错误删掉即可。
然后来运行生成的代码,能看到已经能够成功地发出请求,把返回的 JSON 打印出来。但是现在那个输入是固定的,要从一个变量来输入需要用到 JSON 序列化。
先构造一个包含三个字段的结构体,再定义一个变量,初始化每个结构体成员,再调用 JSON.marshaler 来得到这个序列化之后的字符串。不同于之前这里是个字符串,这里是个字节数组。所以把 strings.newReader 改成 bytes.new ready 来构造 request 上的 body 。然后就能成功地通过一个变量来发送 HTTP 请求。
接下来要把这个 response body 来解析出来。和request一样,写一个结构体,把返回的JSON反序列化到结构体里面。这里用到另一个代码生成工具,打开oktools.net/json2go ,把json字符串粘贴进去,就能够得到对应response结构体。
接下来回到代码,定一个 response 结构体的对象,然后用 JSON.unmarshal 把 body 反序列化到这个结构体里面,再打印出来。
然后我们要打印 response 里面的特定字段。观察 json 可以看出我们需要的结果是在 Dictionary.explanations,用 for range 循环来迭代它,然后直接打印结构,参照一些词典的显示方式,可以在前面打印出这个单词和它的音标。
现在程序的输入还是写死的。要把代码的主体改成一个query函数,查询的单词作为参数传递进来。
最后写一个简单的 main 函数,首先判断一下命令和参数的个数,如果不是两个,就打印出错误信息,退出程序。否则就获取到用户输入的单词,然后执行 query 函数。
至此,命令行词典完成。