这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。
一、初识Go文件结构---输出Hello World!
Go语言开发环境配置参考:Go 语言原理与实践学习资料
1.1 创建xx.go文件
- 所有的
.go文件,除了空行和注释,都应该在第一行声明自己所属的包 - 源文件头部以package xxx声明包名称,即一个目录下的同级源文件属于同一个包
- 包所在的目录名最好不用
main、all、std这三个保留名称!!!! - 可执行文件必须包含
package main和入口函数main,main包是Go语言程序的入口包,一个Go语言程序必须有且仅有一个main包,并且,一个main包中也必须有且仅有一个main函数。 Plus: 权限问题 包中成员以名称首字母大小写决定访问权限 Public: 首字母大写,可被包外访问internal: 首字母小写,仅包内成员可以访问
1.2 敲代码Demo---Hello World!
package main
import (
"fmt"
)
func main(){
fmt.Println("hello world!")
}
运行方式:go run xxx.go
二、简易的猜数字游戏
因为每次需要生成一个随机数,所以需要导入包math/rand
package main
import (
"fmt"
"math/rand"
"time"
)
在main函数中加入下述代码,注意生成随机数需要设置随机数种子,这里采用了时间戳
func main() {
maxNum := 100 //随机数的范围
rand.Seed(time.Now().UnixNano())//时间戳作为随机数种子
secretNumber := rand.Intn(maxNum)
...//开始读取用户键盘输入
}
接下来,就是利用for循环来判断用户猜测的数字是否正确,返回对应的猜测结果,考察了if分支和for循环,以及程序数据的读入,输出格式等
func main() {
...//生成猜测数
var guess int
_, err := fmt.Scanf("%d\r\n", &guess)//在windows系统中这里是\r\n
if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
continue
}
fmt.Println("You guess is", guess)
if guess > secretNumber {
fmt.Println("Your guess is bigger than the secret number. Please try again")
} else if guess < secretNumber {
fmt.Println("Your guess is smaller than the secret number. Please try again")
} else {
fmt.Println("Correct, you Legend!")
break//猜对了则退出for循环
}
}
三、简易版的在线词典翻译
因为老师视频里面采用的是彩云翻译:fanyi.caiyunapp.com/#/ 这里我调用的是火山翻译:translate.volcengine.com/translate
1. 抓包分析请求API
首先,我们需要找到那个调用翻译API的请求,这边我是通过点击图片左边捕捉的一些请求,挨个查看它们各自对应的响应,看返回的数据是否是预期的
2. 自动生成请求,响应结构体
在找到的那个请求上右键->复制->以cURL(bash)格式复制,这部分内容通过一个网址解析,可以为我们自动生成对应的Go代码
通过视频讲解,明显需要两个结构体:一个请求结构体,一个响应结构体
请求结构体由红框处构造
请求结构体定义如下:
type HuoShanRequest struct {
Text string `json:"text"`
Language string `json:"language"`
}
而响应结构体,我们则需要复制预览里面的值,通过另外一个网址解析json数据
- Json转结构体
响应结构体定义如下:
type HuoShanReponse struct {
Words []struct {
Source int `json:"source"`
Text string `json:"text"`
PosList []struct {
Type int `json:"type"`
Phonetics []struct {
Type int `json:"type"`
Text string `json:"text"`
} `json:"phonetics"`
Explanations []struct {
Text string `json:"text"`
Examples []struct {
Type int `json:"type"`
Sentences []struct {
Text string `json:"text"`
TransText string `json:"trans_text"`
} `json:"sentences"`
} `json:"examples"`
Synonyms []interface{} `json:"synonyms"`
} `json:"explanations"`
Relevancys []interface{} `json:"relevancys"`
} `json:"pos_list"`
} `json:"words"`
Phrases []interface{} `json:"phrases"`
BaseResp struct {
StatusCode int `json:"status_code"`
StatusMessage string `json:"status_message"`
} `json:"base_resp"`
}
实现的调用火山翻译API的接口函数
func queryByHuoShan(word string) {
//初始化数据请求结构体
data := HuoShanRequest{
// fill struct
Text: word,
Language: "en",
}
payloadBytes, err := json.Marshal(data)//序列化
if err != nil {
// handle err
log.Fatal(err)
}
body := bytes.NewReader(payloadBytes)
req, err := http.NewRequest("POST", "https://translate.volcengine.com/web/dict/match/v1/", body)
if err != nil {
// handle err
log.Fatal(err)
}
req.Header.Set("Authority", "translate.volcengine.com")
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Referer", "https://translate.volcengine.com")
resp, err := http.DefaultClient.Do(req)
if err != nil {
// handle err
log.Fatal(err)
}
defer resp.Body.Close()
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))
}
var hsp HuoShanReponse
err = json.Unmarshal(bodyText, &hsp)//将响应的字节流数据反序列化成响应结构体
if err != nil {
log.Fatal(err)
}
//核心修改代码
//这里需要注意的是结构体的嵌套关系,从而确定翻译和发音的正确位置
fmt.Println(word, "UK: ", hsp.Words[0].PosList[0].Phonetics[0].Text, "US: ", hsp.Words[0].PosList[0].Phonetics[1].Text)
for _, item := range hsp.Words[0].PosList[0].Explanations {
fmt.Printf("%s\n", item.Text)
}
}
3. 修改代码实现并行请求两个翻译引擎来提高响应速度
常见的实现基于 waitGroup errGroup chan 参考链接:深入浅出 WaitGroup 和 Errgroup
- 我的waitGroup版本
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1)
}
word := os.Args[1]
var wg sync.WaitGroup
wg.Add(2)//添加2个子线程
go func () {
defer wg.Done()//通知主线程结束
fmt.Println("-----彩云翻译-----")
query(word)
}()
go func () {
defer wg.Done()//通知主线程结束
fmt.Println("-----火山翻译-----")
queryByHuoShan(word)
}()
wg.Wait()
fmt.Println("Finish.")
// fmt.Println("-----彩云翻译-----")
// query(word)
// fmt.Println("-----火山翻译-----")
// queryByHuoShan(word)
}