第一天,学了些Golang的基础语法,然后做了三个小项目。
1. 猜数字
随机生成一个0~100的整数,然后猜数,程序很简单,就不贴了。
2. 英汉字典程序
目的:查询一个单词,输出音标和释义,如下所示:
$ go run dictionary.go hello
hello UK: [ˈheˈləu] US: [həˈlo]
int.喂;哈罗
n.引人注意的呼声
v.向人呼(喂)
2.1 用网页的F12功能抓包
打开一个翻译网页,比如 https://fanyi.caiyunapp.com/
按F12可进入开发者工具,里面可以查看network
,然后可以看到好多网页请求。
找到请求方式为“POST”的dict请求,里面有Payload和Preview。
其中,Payload是请求的信息,包含trans_type
和source
两个字段
Preview则是响应信息,包含了查询单词的相关信息,是个非常复杂的结构体
2.2 代码生成
上面这个URL请求可以用Go来写,而且可以自动生成相应代码。步骤如下:
首先,复制cURL。
然后,在 https://curlconverter.com/go/ 网站,把复制的内容粘贴进去,就能自动生成相应的代码
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
var data = strings.NewReader(`{"trans_type":"en2zh","source":"hello"}`)
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("authority", "api.interpreter.caiyunai.com")
req.Header.Set("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6")
req.Header.Set("app-name", "xy")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "e3da338b14045a9a8f59777769d1c977")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Microsoft Edge";v="111", "Not(A:Brand";v="8", "Chromium";v="111"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Linux"`)
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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
最后输出的是web响应结果的json字符串:
{"rc":0,"wiki":{},"dictionary":{"prons":{"en-us":"[h\u0259\u02c8lo]","en":"[\u02c8he\u02c8l\u0259u]"},"explanations":["int.\u5582;\u54c8\u7f57","n.\u5f15\u4eba\u6ce8\u610f\u7684\u547c\u58f0","v.\u5411\u4eba\u547c(\u5582)"],"synonym":["greetings","salutations"],"antonym":[],"wqx_example":[["say hello to","\u5411\u67d0\u4eba\u95ee\u5019,\u548c\u67d0\u4eba\u6253\u62db\u547c"],["Say hello to him for me . ","\u4ee3\u6211\u95ee\u5019\u4ed6\u3002"]],"entry":"hello","type":"word","related":[],"source":"wenquxing"}}
2.3 JSON转换
web请求和响应的数据采用JSON格式,可以将其转化为Go结构体。
请求的结构体比较简单,可以直接手写:
type DictRequest struct {
TransType string `json:"trans_type"` // 表示翻译方式,比如英译中
Source string `json:"source"` // 表示要翻译的单词
}
而响应的结构体非常复杂,依旧可以用代码生成:
在F12工具中,找到Preview,然后复制
进入 https://oktools.net/json2go 把刚刚复制的粘贴进去,然后就能把JSON字符串转为Go结构体:
type DictResponse struct {
Rc int `json:"rc"`
Wiki struct {
} `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 []interface{} `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"`
}
和JSON转换相关的函数:
// 结构体 -> JSON字符串
func json.Marshal(v any) ([]byte, error)
// JSON字符串 -> 结构体
func json.Unmarshal(data []byte, v any) error
用法如下:
import (
"encoding/json"
"log"
// ...
)
func main() {
// ...
request := DictRequest{TransType: "en2zh", Source: word}
buf, err := json.Marshal(request)
if err != nil {
log.Fatal(err)
}
// ...
var response DictResponse
err = json.Unmarshal(bodyText, &response)
if err != nil {
log.Fatal(err)
}
}
2.4 os 包
用 os 包可以读取程序的输入参数(类似C/C++的main参数),也能使用os.Exit()
提前退出程序,实例如下:
if len(os.Args) != 2 {
fmt.Println("usage error: need a input word")
os.Exit(-1)
}
2.5 完整程序
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
}
type DictResponse struct {
Rc int `json:"rc"`
Wiki struct {
} `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 []interface{} `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 query(word string) {
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: word}
buf, err := json.Marshal(request)
if err != nil {
log.Fatal(err)
}
data := bytes.NewReader(buf)
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("authority", "api.interpreter.caiyunai.com")
req.Header.Set("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "en-US,en;q=0.9,zh-CN;q=0.8,zh-TW;q=0.7,zh;q=0.6")
req.Header.Set("app-name", "xy")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "e3da338b14045a9a8f59777769d1c977")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Microsoft Edge";v="111", "Not(A:Brand";v="8", "Chromium";v="111"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Linux"`)
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 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
var response DictResponse
err = json.Unmarshal(bodyText, &response)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s UK: %s US: %s\n", response.Dictionary.Entry, response.Dictionary.Prons.En, response.Dictionary.Prons.EnUs)
for i := 0; i < len(response.Dictionary.Explanations); i++ {
fmt.Printf("%s\n", response.Dictionary.Explanations[i])
}
}
func main() {
if len(os.Args) != 2 {
fmt.Println("usage error: need a input word")
os.Exit(-1)
}
query(os.Args[1])
}
结果如下:
$ go run dictionary.go hello
hello UK: [ˈheˈləu] US: [həˈlo]
int.喂;哈罗
n.引人注意的呼声
v.向人呼(喂)
$ go run dictionary.go beauty
beauty UK: [ˈbjuːti] US: [ˈbjutɪ]
n.美人;美丽;美观;佳丽;美的事物;好处;优点
3. SOCKS5 代理
未完待续…