笔记1 [语言基础] Go语言上手-基础语言 | 青训营笔记

118 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。

主要是对三个课程作业的记录。

1. 修改第一个例子猜谜游戏里面的最终代码,使用 fmt.Scanf 来简化代码实现

这个题目比较简单。王老师在直播中提到了,他给出的代码用 bufio.NewReader(os.Stdin) 这种比较麻烦的方式是因为后面的 socket 代理项目会用到,所以让我们提前熟悉一下。实际上,用 fmt.Scanf 可以很方便的实现用户输入数字的获取。

6U)Q)AVN`V3NT$}RFL~B)~8.png

通过查看 fmt.Scanf 的源码,如上图,可以看到 fmt.Scanf 会调用 Fsanf, 默认从标准输入中读取。我们需要提供两个参数,一个是输入的格式,这里是数字,就用 "%d"; 另一个是接收该输入的接口,我们就用一个int变量的引用来接收即可。关键部分的实现如下:

var guess int
_, err := fmt.Scanf("%d", &guess)

2. 修改第二个例子命令行词典里面的最终代码,增加另一种翻译引擎的支持

这个题目花了我比较长的时间。我尝试了谷歌翻译、百度翻译、必应翻译、搜狗翻译等等,发现他们在请求头的payload部分都不是像彩云翻译那样是一个简单的 json 序列,而是 Query string parameters 和 form data 的形式。于是,我选择搜狗翻译,尝试处理这个 form data 的构造。

查询单词“world”时,搜狗翻译的 form data 如下:

2.png

可以看到“world”是text参数的值。因此我尝试采用字符串拼接的方式,构造整个form data。插一句题外话,form data 中有一个 uuid,由于我使用搜狗翻译时也没有进行登录账号的操作,因此我认为这个 uuid 没啥认证作用。为了验证我这个猜想,我把 uuid 改成了同样位数的全 1 序列。综上,字符串拼接部分的代码如下所示:

3.png

其中,变量 word 是用户在命令行输入的想要查询的单词。其他步骤就和老师视频里面一样。要把请求的 curl 代码转换成 go 代码,结合我们生成的 form data 部分构造用户命令行输入的单词查询请求发给搜狗翻译的接口。最后,将相应的 json 序列转化成 go 结构体,然后输出结构体中单词释义的部分即可。这里不再赘述了,用到的两个网站链接如下: curlconverter json2go

最终实现的效果如下。

截图 2022-05-07 20-55-31.png

3. 在上一步骤的基础上,修改代码实现并行请求两个翻译引擎来提高响应速度

这个就比较简单了。我们在 main 函数中声明两个无缓冲的 chan 。在 main goroutine 中,我们再开两个子 goroutine,里面分别调用两个搜索引擎的查询,当查询结束时,向各自的 chan 中发送一个信号(用的空结构体,这里没啥实际意义,就是想告诉 main goroutine 当前的子 goroutine结束了)。在 main goroutine中,接收者两个 chan。如果 chan 对应的子 goroutine 没有结束,那么 chan 的接收一直被阻塞。这样的效果就是,只有两个子 goroutine 都结束了,整个程序才会退出,从而防止了 goroutine 的泄露(就是说 main goroutine 运行结束退出了,但创建的子 goroutine 没有运行结束退出)。关键部分代码如下:

// main函数部分
done1 := make(chan struct{})
done2 := make(chan struct{})
go func() {
        query1(word) // 调用彩云小译
        fmt.Println("caiyun is done!")
        done1 <- struct{}{}
}()
go func() {
        query2(word) // 调用搜狗翻译
        fmt.Println("sougou is done!")
        done2 <- struct{}{}
}()
<-done1
<-done2

最终效果如下:

截图 2022-05-07 21-10-03.png