Go语言学习(二) 在线词典项目|青训营笔记

2023-10-22 00:40

本文主要是介绍Go语言学习(二) 在线词典项目|青训营笔记,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Go 语言学习(二) 在线词典项目_青训营笔记

  • Go 语言学习(二) 在线词典项目_青训营笔记
    • 一、在线词典项目介绍
    • 二、开发步骤
      • 1. 抓包
      • 2. 代码生成
      • 3. 生成 request body
      • 4. 解析 request body
      • 5. 打印结果
    • 三、代码展示
      • 1. 主函数
      • 2. 彩云翻译函数
      • 3. 百度翻译函数

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

一、在线词典项目介绍

用户可以在命令行里面查询一个单词。此程序能通过调用第三方的 API 查询到单词的翻译并打印出来。

在这个项目里面,我学习了如何用 go 语言来发送 HTTP 请求、解析 json,学习了如何使用代码生成来提高开发效率。

在线词典介绍.png

二、开发步骤

1. 抓包

  • 要用到的 API 是彩云科技提供的在线翻译。先打开彩云翻译的网页,然后右键检查打开浏览器的开发者工具。

抓包1.png

  • 此时点击翻译按钮,浏览器会发送一系列请求,找到查询单词的请求。这是一个 HTTP 的 post 的请求,请求的 header 是一个 json,里面有两个字段,代表要翻译的语言和查询的单词。API 的返回结果里面会有 Wiki 和 dictionary 两个字段。需要用的结果主要在 dictionary.Explanations 字段里面,其他字段里面还包括音标等信息。

抓包2.png

抓包3.png

抓包4.png

2. 代码生成

  • 需要在 Golang 里面去发送这个请求。但是这个请求比较复杂,用代码构造很麻烦。可以用一种简单的方式来生成代码,右键浏览器里面的 copy as curl,在终端粘贴一下 curl 命令,可以返回一大串 json。

代码生成1.png

代码生成2.png

  • 打开代码生成网站,粘贴 curl 请求,即可自动生成 Golang 代码。

代码生成3.png

3. 生成 request body

  • 在 Golang 里面,需要生成一段 JSON ,常用的方式是先构造出来一个结构体,这个结构体和需要生成的 JSON 的结构是一一对应的。

生成 request body1.png

4. 解析 request body

  • 接下来把这个 response body 来解析出来。在 js/Python 这些脚本语言里面,body 是一个字典或者 map 的结构, 可以直接从里面取值,但是 golang 是个强类型语言,这种做法并不是最佳实践。更常用的方式是和 request 的一样,写一个结构体,把返回的 JSON 反序列化到结构体里面。但是在浏览器里面可以看到这个 API 返回的结构非常复杂,如果要一一定义结构体字段,非常繁琐并且容易出错。

解析 request body1.png

  • 此时可以使用对应的代码生成工具 ,把 json 字符串粘贴进去,自动生成对应结构体。

解析 request body2.png

5. 打印结果

  • 观察那个 json 可以看出需要的结果是在 Dictionary.explanations 里的,用 for range 循环来迭代它,然后直接打印结构,参照一些词典的显示方式,可以在前面打印出这个单词和它的音标。

打印结果.png

三、代码展示

经过课后编程实践,我实现了并行请求两个翻译引擎来提高响应速度。

下面是我的代码展示,包含了代码详细注释,便于理解。

1. 主函数

package mainimport ("fmt""os""sync""time"
)func main() { //此在线词典程序需要在 Git Bash终端命令行运行,如输入 go run *.go hellostart := time.Now()if len(os.Args) != 2 { // Args 保存命令行参数,以程序名称开头,这里第2个参数为要查询的单词fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello`) // Fprintf() 根据格式说明符格式化并写入 os.Stderr 。它返回写入的字节数和遇到的任何写入错误。os.Exit(1)}word := os.Args[1]wg := sync.WaitGroup{} // WaitGroup() 等待一组 goroutine 完成,主 goroutine 调用 Add() 来设置要等待的 goroutine 的数量,然后每个 goroutine 运行并在完成时调用Done(),同时, Wait()可以用来阻塞,直到所有的 goroutine 都完成wg.Add(2)              //将可能为负的增量添加到 WaitGroup() 计数器,如果计数器变为零,则所有在 Wait() 上阻塞的 goroutine 都会被释放,如果计数器变为负数,请添加错误处理go QueryCaiYun(word, &wg)go QueryBaiDu(word, &wg)wg.Wait()finish := time.Now()fmt.Println("runtime:", finish.Sub(start))
}

2. 彩云翻译函数

package mainimport ("bytes""encoding/json""fmt""io/ioutil""log""net/http""sync"
)type CaiYunDictRequest struct {TransType string `json:"trans_type"`Source    string `json:"source"`UserID    string `json:"user_id"`
}type CaiYunDictResponse struct {Rc   int `json:"rc"`Wiki struct {KnownInLaguages int `json:"known_in_laguages"`Description     struct {Source string      `json:"source"`Target interface{} `json:"target"`} `json:"description"`ID   string `json:"id"`Item struct {Source string `json:"source"`Target string `json:"target"`} `json:"item"`ImageURL  string `json:"image_url"`IsSubject string `json:"is_subject"`Sitelink  string `json:"sitelink"`} `json:"wiki"`Dictionary struct {Prons struct {EnUs string `json:"en-us"`En   string `json:"en"`} `json:"prons"`Explanations []string      `json:"explanations"`Synonym      []string      `json:"synonym"`Antonym      []string      `json:"antonym"`WqxExample   [][]string    `json:"wqx_example"`Entry        string        `json:"entry"`Type         string        `json:"type"`Related      []interface{} `json:"related"`Source       string        `json:"source"`} `json:"dictionary"`
}func QueryCaiYun(word string, wg *sync.WaitGroup) {client := &http.Client{} //定义客户// var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`) //把输入的字符串 data 转换成流 reqrequest := CaiYunDictRequest{TransType: "en2zh", Source: word}buf, err := json.Marshal(request) // Marshal() 返回 request 的 JSON 编码,序列化为一个 byte 数组。if err != nil {log.Fatal(err) //打印日志,退出程序}var data = bytes.NewReader(buf) //把输入的 byte 数组转换成流 req/* 创建请求 */req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)if err != nil {log.Fatal(err) //打印日志,退出程序}/* 设置请求头 */req.Header.Set("Accept", "application/json, text/plain, */*")req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")req.Header.Set("Connection", "keep-alive")req.Header.Set("Content-Type", "application/json;charset=UTF-8")req.Header.Set("Origin", "https://fanyi.caiyunapp.com")req.Header.Set("Referer", "https://fanyi.caiyunapp.com/")req.Header.Set("Sec-Fetch-Dest", "empty")req.Header.Set("Sec-Fetch-Mode", "cors")req.Header.Set("Sec-Fetch-Site", "cross-site")req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44")req.Header.Set("X-Authorization", "token:qgemv4jr1y38jyq6vhvi")req.Header.Set("app-name", "xy")req.Header.Set("os-type", "web")req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100"`)req.Header.Set("sec-ch-ua-mobile", "?0")req.Header.Set("sec-ch-ua-platform", `"Windows"`)/* 发起请求 */resp, err := client.Do(req)if err != nil {log.Fatal(err) //打印日志,退出程序}defer resp.Body.Close() //defer 会在函数结束后从后往前触发,Close() 手动关闭 Body流,防止内存资源泄露/*读取响应*/bodyText, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatal(err) //打印日志,退出程序}if resp.StatusCode != 200 { // 防御式编程,判断状态码是否正确log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText)) //打印日志,退出程序}// fmt.Printf("%s\n", bodyText)var dictResponse CaiYunDictResponseerr = json.Unmarshal(bodyText, &dictResponse) //Unmarshal()解析 bodyText的 JSON 编码的数据并反序列化将结果存储在 dictResponse 指向的值中。if err != nil {log.Fatal(err) //打印日志,退出程序}// fmt.Printf("%#v\n", dictResponse)fmt.Println("--------------------彩云翻译-----------------------")fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)for _, item := range dictResponse.Dictionary.Explanations {fmt.Println(item)}wg.Done()
}

3. 百度翻译函数

package mainimport ("bytes""encoding/json""fmt""io/ioutil""log""net/http""sync"
)type BaiDuDictRequest struct {Query  string `json:"query"`UserID string `json:"user_id"`
}type BaiDuDictResponse struct {TransResult struct {Data []struct {Dst        string          `json:"dst"`PrefixWrap int             `json:"prefixWrap"`Result     [][]interface{} `json:"result"`Src        string          `json:"src"`} `json:"data"`From     string `json:"from"`Status   int    `json:"status"`To       string `json:"to"`Type     int    `json:"type"`Phonetic []struct {SrcStr string `json:"src_str"`TrgStr string `json:"trg_str"`} `json:"phonetic"`} `json:"trans_result"`DictResult struct {Edict struct {Item []struct {TrGroup []struct {Tr          []string      `json:"tr"`Example     []interface{} `json:"example"`SimilarWord []string      `json:"similar_word"`} `json:"tr_group"`Pos string `json:"pos"`} `json:"item"`Word string `json:"word"`} `json:"edict"`Collins struct {Entry []struct {EntryID string `json:"entry_id"`Type    string `json:"type"`Value   []struct {MeanType []struct {InfoType string `json:"info_type"`InfoID   string `json:"info_id"`Example  []struct {ExampleID string `json:"example_id"`TtsSize   string `json:"tts_size"`Tran      string `json:"tran"`Ex        string `json:"ex"`TtsMp3    string `json:"tts_mp3"`} `json:"example"`} `json:"mean_type"`Gramarinfo []interface{} `json:"gramarinfo"`Tran       string        `json:"tran"`Def        string        `json:"def"`MeanID     string        `json:"mean_id"`Posp       []struct {Label string `json:"label"`} `json:"posp"`} `json:"value"`} `json:"entry"`WordName      string `json:"word_name"`Frequence     string `json:"frequence"`WordEmphasize string `json:"word_emphasize"`WordID        string `json:"word_id"`} `json:"collins"`From        string `json:"from"`SimpleMeans struct {WordName  string   `json:"word_name"`From      string   `json:"from"`WordMeans []string `json:"word_means"`Exchange  struct {WordPl  []string `json:"word_pl"`WordEst []string `json:"word_est"`WordEr  []string `json:"word_er"`} `json:"exchange"`Tags struct {Core  []string `json:"core"`Other []string `json:"other"`} `json:"tags"`Symbols []struct {PhEn  string `json:"ph_en"`PhAm  string `json:"ph_am"`Parts []struct {Part  string   `json:"part"`Means []string `json:"means"`} `json:"parts"`PhOther string `json:"ph_other"`} `json:"symbols"`} `json:"simple_means"`Lang   string `json:"lang"`Oxford struct {Entry []struct {Tag  string `json:"tag"`Name string `json:"name"`Data []struct {Tag  string `json:"tag"`Data []struct {Tag   string `json:"tag"`P     string `json:"p"`PText string `json:"p_text"`} `json:"data"`} `json:"data"`} `json:"entry"`Unbox []struct {Tag  string `json:"tag"`Type string `json:"type"`Name string `json:"name"`Data []struct {Tag     string   `json:"tag"`Text    string   `json:"text,omitempty"`Words   []string `json:"words,omitempty"`Outdent string   `json:"outdent,omitempty"`Data    []struct {Tag    string `json:"tag"`EnText string `json:"enText"`ChText string `json:"chText"`} `json:"data,omitempty"`} `json:"data"`} `json:"unbox"`} `json:"oxford"`Sanyms []struct {Tit  string `json:"tit"`Type string `json:"type"`Data []struct {P string   `json:"p"`D []string `json:"d"`} `json:"data"`} `json:"sanyms"`Usecase struct {Idiom []struct {P    string `json:"p"`Tag  string `json:"tag"`Data []struct {Tag  string `json:"tag"`Data []struct {EnText string `json:"enText"`Tag    string `json:"tag"`ChText string `json:"chText"`Before []struct {Tag  string `json:"tag"`Data []struct {EnText string `json:"enText"`Tag    string `json:"tag"`ChText string `json:"chText"`} `json:"data"`} `json:"before,omitempty"`} `json:"data"`} `json:"data"`} `json:"idiom"`} `json:"usecase"`BaiduPhrase []struct {Tit   []string `json:"tit"`Trans []string `json:"trans"`} `json:"baidu_phrase"`QueryExplainVideo struct {ID           int    `json:"id"`UserID       string `json:"user_id"`UserName     string `json:"user_name"`UserPic      string `json:"user_pic"`Query        string `json:"query"`Direction    string `json:"direction"`Type         string `json:"type"`Tag          string `json:"tag"`Detail       string `json:"detail"`Status       string `json:"status"`SearchType   string `json:"search_type"`FeedURL      string `json:"feed_url"`Likes        string `json:"likes"`Plays        string `json:"plays"`CreatedAt    string `json:"created_at"`UpdatedAt    string `json:"updated_at"`DuplicateID  string `json:"duplicate_id"`RejectReason string `json:"reject_reason"`CoverURL     string `json:"coverUrl"`VideoURL     string `json:"videoUrl"`ThumbURL     string `json:"thumbUrl"`VideoTime    string `json:"videoTime"`VideoType    string `json:"videoType"`} `json:"queryExplainVideo"`} `json:"dict_result"`LijuResult struct {Double string   `json:"double"`Tag    []string `json:"tag"`Single string   `json:"single"`} `json:"liju_result"`Logid int64 `json:"logid"`
}func QueryBaiDu(word string, wg *sync.WaitGroup) {client := &http.Client{} //定义客户// var data = strings.NewReader(`query=good`) //把输入的字符串 data 转换成流 reqrequest := BaiDuDictRequest{Query: word}buf, err := json.Marshal(request) // Marshal() 返回 request 的 JSON 编码,序列化为一个 byte 数组。if err != nil {log.Fatal(err) //打印日志,退出程序}var data = bytes.NewReader(buf) //把输入的 byte 数组转换成流 req/* 创建请求 */req, err := http.NewRequest("POST", "https://fanyi.baidu.com/langdetect", data)if err != nil {log.Fatal(err) //打印日志,退出程序}/* 设置请求头 */req.Header.Set("Accept", "*/*")req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")req.Header.Set("Connection", "keep-alive")req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")req.Header.Set("Cookie", `BIDUPSID=2860D678CCB10886990D4D819CC24BAB; PSTM=1603262095; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; __yjs_duid=1_3242d9ae5ec151bc4e7e9d908fe0e54c1620968286434; BDUSS=g3Tm93dWtraHZkRUdsdzlJeDEyalp2RmpZOW1RNmlDMUV3d2N0M0c4Z0pqNXhoRVFBQUFBJCQAAAAAAAAAAAEAAABffmtXxKnTsNChutpYSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCdWEJAnVhfk; BDUSS_BFESS=g3Tm93dWtraHZkRUdsdzlJeDEyalp2RmpZOW1RNmlDMUV3d2N0M0c4Z0pqNXhoRVFBQUFBJCQAAAAAAAAAAAEAAABffmtXxKnTsNChutpYSAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkCdWEJAnVhfk; APPGUIDE_10_0_2=1; BAIDUID=3A21E0D3A023E0BF48D5E6AB59882FC3:SL=0:NR=20:FG=1; MAWEBCUID=web_ZbMGPxbtNTJgOhwuypnUUKjyVeChjrWNsCSTdnAIkJyWEtWEYb; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1652153403,1652175540,1652186130,1652278875; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1652506784; delPer=0; PSINO=1; BAIDUID_BFESS=3A21E0D3A023E0BF48D5E6AB59882FC3:SL=0:NR=20:FG=1; RT="z=1&dm=baidu.com&si=hqolag82j09&ss=l35hyf6s&sl=2&tt=56c&bcn=https%3A%2F%2Ffclog.baidu.com%2Flog%2Fweirwood%3Ftype%3Dperf&ld=5ne&ul=2axq&hd=2b02"; BA_HECTOR=24052g04012lag8kt41h7ulf10q; BDRCVFR[OEHfjv-pq1f]=mk3SLVN4HKm; BDRCVFR[dG2JNJb_ajR]=mk3SLVN4HKm; BDRCVFR[-pGxjrCMryR]=mk3SLVN4HKm; H_PS_PSSID=`)req.Header.Set("Origin", "https://fanyi.baidu.com")req.Header.Set("Referer", "https://fanyi.baidu.com/?aldtype=16047")req.Header.Set("Sec-Fetch-Dest", "empty")req.Header.Set("Sec-Fetch-Mode", "cors")req.Header.Set("Sec-Fetch-Site", "same-origin")req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36 Edg/100.0.1185.44")req.Header.Set("X-Requested-With", "XMLHttpRequest")req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="100", "Microsoft Edge";v="100"`)req.Header.Set("sec-ch-ua-mobile", "?0")req.Header.Set("sec-ch-ua-platform", `"Windows"`)/* 发起请求 */resp, err := client.Do(req)if err != nil {log.Fatal(err) //打印日志,退出程序}defer resp.Body.Close() //defer 会在函数结束后从后往前触发,Close() 手动关闭 Body流,防止内存资源泄露/*读取响应*/bodyText, err := ioutil.ReadAll(resp.Body)if err != nil {log.Fatal(err) //打印日志,退出程序}if resp.StatusCode != 200 { // 防御式编程,判断状态码是否正确log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText)) //打印日志,退出程序}// fmt.Printf("%s\n", bodyText)var dictResponse BaiDuDictResponseerr = json.Unmarshal(bodyText, &dictResponse) //Unmarshal()解析 bodyText的 JSON 编码的数据并反序列化将结果存储在 dictResponse 指向的值中。if err != nil {log.Fatal(err) //打印日志,退出程序}// fmt.Printf("%#v\n", dictResponse)fmt.Println("--------------------百度翻译-----------------------")fmt.Println(word, "UK:", dictResponse.DictResult.SimpleMeans.Symbols, "US:", dictResponse.DictResult.SimpleMeans.Symbols)for _, item := range dictResponse.DictResult.SimpleMeans.WordMeans {fmt.Println(item)}wg.Done()
}

这篇关于Go语言学习(二) 在线词典项目|青训营笔记的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/257968

相关文章

使用SQL语言查询多个Excel表格的操作方法

《使用SQL语言查询多个Excel表格的操作方法》本文介绍了如何使用SQL语言查询多个Excel表格,通过将所有Excel表格放入一个.xlsx文件中,并使用pandas和pandasql库进行读取和... 目录如何用SQL语言查询多个Excel表格如何使用sql查询excel内容1. 简介2. 实现思路3

Go语言实现将中文转化为拼音功能

《Go语言实现将中文转化为拼音功能》这篇文章主要为大家详细介绍了Go语言中如何实现将中文转化为拼音功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 有这么一个需求:新用户入职 创建一系列账号比较麻烦,打算通过接口传入姓名进行初始化。想把姓名转化成拼音。因为有些账号即需要中文也需要英

Go语言使用Buffer实现高性能处理字节和字符

《Go语言使用Buffer实现高性能处理字节和字符》在Go中,bytes.Buffer是一个非常高效的类型,用于处理字节数据的读写操作,本文将详细介绍一下如何使用Buffer实现高性能处理字节和... 目录1. bytes.Buffer 的基本用法1.1. 创建和初始化 Buffer1.2. 使用 Writ

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

Python 中 requests 与 aiohttp 在实际项目中的选择策略详解

《Python中requests与aiohttp在实际项目中的选择策略详解》本文主要介绍了Python爬虫开发中常用的两个库requests和aiohttp的使用方法及其区别,通过实际项目案... 目录一、requests 库二、aiohttp 库三、requests 和 aiohttp 的比较四、requ

SpringBoot项目启动后自动加载系统配置的多种实现方式

《SpringBoot项目启动后自动加载系统配置的多种实现方式》:本文主要介绍SpringBoot项目启动后自动加载系统配置的多种实现方式,并通过代码示例讲解的非常详细,对大家的学习或工作有一定的... 目录1. 使用 CommandLineRunner实现方式:2. 使用 ApplicationRunne

使用IntelliJ IDEA创建简单的Java Web项目完整步骤

《使用IntelliJIDEA创建简单的JavaWeb项目完整步骤》:本文主要介绍如何使用IntelliJIDEA创建一个简单的JavaWeb项目,实现登录、注册和查看用户列表功能,使用Se... 目录前置准备项目功能实现步骤1. 创建项目2. 配置 Tomcat3. 项目文件结构4. 创建数据库和表5.

Go Gorm 示例详解

《GoGorm示例详解》Gorm是一款高性能的GolangORM库,便于开发人员提高效率,本文介绍了Gorm的基本概念、数据库连接、基本操作(创建表、新增记录、查询记录、修改记录、删除记录)等,本... 目录1. 概念2. 数据库连接2.1 安装依赖2.2 连接数据库3. 数据库基本操作3.1 创建表(表关

Python项目打包部署到服务器的实现

《Python项目打包部署到服务器的实现》本文主要介绍了PyCharm和Ubuntu服务器部署Python项目,包括打包、上传、安装和设置自启动服务的步骤,具有一定的参考价值,感兴趣的可以了解一下... 目录一、准备工作二、项目打包三、部署到服务器四、设置服务自启动一、准备工作开发环境:本文以PyChar

多模块的springboot项目发布指定模块的脚本方式

《多模块的springboot项目发布指定模块的脚本方式》该文章主要介绍了如何在多模块的SpringBoot项目中发布指定模块的脚本,作者原先的脚本会清理并编译所有模块,导致发布时间过长,通过简化脚本... 目录多模块的springboot项目发布指定模块的脚本1、不计成本地全部发布2、指定模块发布总结多模