基础知识 | 青训营笔记
这是我参与「第三届青训营 -后端场」笔记创作活动的的第2篇笔记
开发环境win10/wsl2, vscode+go插件,主要总结三个实战部分
1 简介
1.1 特点
高性能、高并发
语法简单、学习曲线平缓
丰富的标准库
完善的工具链
静态链接
快速编译:微服务编译速度1min、增量编译小于1s
跨平台
垃圾回收
2 实战入门
2.1 猜数字
v1版本:
func main() {
maxNum := 100
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
}
使用rand.Intn()生成随机数,但是每次生成数字都相同
使用当前时间作为随机种子,从而生成每次不同的数字
v2:
func main() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
}
v3版本增加了获取用户输入,使用bufio.NewReader读取一行内容
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
input = strings.TrimSuffix(input, "\n")//删除最后换行符
顺便总结一下其他获取标准输入方式
//bufio.NewScanner读取一行
input := bufio.NewScanner(os.Stdin)
input.Scan()
str := input.Text()
//Scanln读取一行
var n string
fmt.Scanln(&n)
//Scanf
var guess int
fmt.Scanf("%d", &guess)
2.2 翻译
使用post请求将需要翻译的内容发送给彩云翻译,根据返回的Response获取翻译结果
在翻译界面右键->检查->network找到对应的post请求

payload与preview分别是Request内容与Response内容


获取Request内容
对翻译请求copy curl并将其粘贴到curlconverter.com/#go中获取golan…
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)
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,zh-TW;q=0.8,en-US;q=0.7,en;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/101.0.4951.54 Safari/537.36")
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="101", "Google Chrome";v="101"`)
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()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
将请求封装为struct,并使用json.Marshal序列化
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string `json:"user_id"`
}
...
request := DictRequest{TransType: "en2zh", Source: "good"}
buf, err := json.Marshal(request)
if err != nil {
log.Fatal(err)
}
var data = bytes.NewReader(buf)
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
获取Response结构体
复制preview内容至oktools.net/json2go转换出R…
type DictResponse 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"`
}
将获取到的bodyText反序列化得到Response并输出需要的内容
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item)
}
作业相关
需求:增加另外一种翻译方式并并行翻译
尝试有道翻译
有道翻译的请求为form data格式而非彩云翻译的json格式

i=good&from=AUTO&to=AUTO&smartresult=dict&client=fanyideskweb&salt=16519067160016&sign=49d2f830da995315a642d51046ffe008<s=1651906716001&bv=247811f9b7fd387f154bf67d8ebd44f3&doctype=json&version=2.1&keyfrom=fanyi.web&action=FY_BY_REALTlME
直接拼接字符串,我在实现时还是定义了结构体,使用reflect对遍历结构体每个Field并拼接进字符串
type youdaoResponse struct {
TranslateResult [][]struct {
Tgt string `json:"tgt"`
Src string `json:"src"`
} `json:"translateResult"`
ErrorCode int `json:"errorCode"`
Type string `json:"type"`
SmartResult struct {
Entries []string `json:"entries"`
Type int `json:"type"`
} `json:"smartResult"`
}
...
request := youdaoRequest{
i: word,
from: "AUTO",
to: "AUTO",
smartresult: "dict",
client: "fanyideskweb",
salt: "16519067160016",
sign: "49d2f830da995315a642d51046ffe008",
lts: "1651906716001",
bv: "247811f9b7fd387f154bf67d8ebd44f3",
doctype: "json",
version: "2.1",
keyfrom: "fanyi.web",
action: "FY_BY_REALTlME",
}
body := ""
v := reflect.ValueOf(request)
t := reflect.TypeOf(request)
for i := 0; i < v.NumField(); i++ {
if i != 0 {
body += "&"
}
body += t.Field(i).Name + "=" + v.Field(i).String()
}
data := strings.NewReader(body)
client := &http.Client{}
req, err := http.NewRequest("POST", "https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule", data)
...
并行翻译部分直接起两个协程即可,使用waitgroup等待两个协程运行结束后再退出。
使用printChan保证同一时间只输出一个结果,防止交叉输出结果
func main() {
var word string
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1)
}
var wg sync.WaitGroup
printChan := make(chan struct{}, 1)
printChan <- struct{}{}
word = os.Args[1]
wg.Add(2)
go caiyunQuery(word, &wg, printChan)
go youdaoQuery(word, &wg, printChan)
wg.Wait()
}