这是我参与「第五届青训营」伴学笔记创作活动的第 2 天,今天主要对Go基础课程的词典项目进行总结。
Go基础课程项目
1. 项目回顾
第二节课中,老师带我们做了三个实战项目,其中第一个猜数项目较为简单,这里不再赘述。第三个项目涉及到的SOCKS5协议之前没有接触过且代码较为冗杂,因此暂时没有深究,只是大概看懂流程。而第二个翻译项目结果较为直观,且通过爬虫->请求代码生成->接收json结构的代码生成->解析输出结果这一流程,让我学习到了一些新知识。特别是代码生成技术,我之前从未接触过,之前在一些抓包的任务中,都是通过手工请求,手工解析结果的方式来满足需求,非常繁琐。今天学习到的通过浏览器curl信息生成对应语言的请求代码,并通过浏览器的响应生成对应语言的JSON处理代码,让我受益匪浅。
2. 课后作业
老师在课后布置了三个作业,前两个作业较为简单,第三个作业则需要增添一个翻译引擎,并且并发加快返回速度。
因为对Go并发编程略有生疏,因此这一部分的作业花费了较多的时间来处理并发请求。因此在这里进行总结,第三个作业主要的处理思路如下:
- 首先,我们根据老师教授的代码生成方法,抓取百度翻译的API,这一步只要按着课堂中的方法做没有问题。
- 由于需要并发运行两部分代码,因此在主函数中需要使用
go func1(), go func2()的形式同时运行两个函数。 - 最后是作业的难点,对两个函数的运行进行并发地选择,哪个函数返回结果更快,则直接将最快查询得到的结果呈现给用户,从而达到了提升查询速度的目的。
对于最后一点,需要通过Go语言中的channel进行实现。具体的实现逻辑如下:
- 首先需要对翻译引擎进行一点小小的修改,把查询到的结果先保存到一个字符串中,随后将字符串送到channel中。
// 彩云翻译引擎
// 获取翻译引擎的查询结果
rst := "彩云翻译:\n"
rst += "UK:" + dictResponse.Dictionary.Prons.En + " US:" + dictResponse.Dictionary.Prons.EnUs
rst += "\n"
for _, item := range dictResponse.Dictionary.Explanations {
rst += (item + "\n")
}
// 返回到通道中
ch <- rst
// 百度翻译引擎也与上面类似
rst := "百度翻译:\n"
for _, item := range dictResponse.Data {
rst = rst + item.K + item.V + "\n"
}
ch <- rst
- 当公共channel一接收到其中一个引擎的结果,便立即打印显示结果,这样便实现了最快返回查询结果的目的。
// 定义一个无缓冲区的公共channel,两个翻译引擎都将结果返回到该channel中
ch := make(chan string)
defer close(ch)
go CaiYunQuery(word, ch)
go BaiduQuery(word, ch)
// 当channel中存在结果时,立即显示结果
res := <-ch
fmt.Println(res)