命令行词典续
代码生成
在上一期我们已经获得了 cURL 命令并且确实返回了一段 JSON,接下来用这个命令来生成 Go 代码:
$ curl 'https://api.interpreter.caiyunai.com/v1/dict' \
> -H 'authority: api.interpreter.caiyunai.com' \
> -H 'accept: application/json, text/plain, */*' \
> -H 'accept-language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7' \
> -H 'app-name: xy' \
> -H 'content-type: application/json;charset=UTF-8' \
> -H 'device-id: 784ac192abb9cce5d326768950e7ce59' \
> -H 'origin: https://fanyi.caiyunapp.com' \
> -H 'os-type: web' \
> -H 'os-version;' \
> -H 'referer: https://fanyi.caiyunapp.com/' \
> -H 'sec-ch-ua: "Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"' \
> -H 'sec-ch-ua-mobile: ?0' \
> -H 'sec-ch-ua-platform: "Windows"' \
> -H 'sec-fetch-dest: empty' \
> -H 'sec-fetch-mode: cors' \
> -H 'sec-fetch-site: cross-site' \
> -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/113.0.0.0 Safari/537.36' \
> -H 'x-authorization: token:qgemv4jr1y38jyq6vhvi' \
> --data-raw '{"trans_type":"en2zh","source":"snoopy"}' \
> --compressed
{"rc":0,"wiki":{},"dictionary":{"prons":{"en-us":"[\u02c8snup\u026a]","en":"[\u02c8snu\u02d0pi]"},"explanations":["a.\u7231\u7ba1\u95f2\u4e8b\u7684;\u7231\u63a2\u542c\u7684;\u7231\u7aa5\u63a2\u7684"],"synonym":[],"antonym":[],"wqx_example":[],"entry":"snoopy","type":"word","related":[],"source":"wenquxing"}}
首先到生成器的网页:curlconverter.com/go/
把前面复制的命令粘贴到这个网页的文本框里,底下选 Go,就能生成等效的代码。
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
var data = strings.NewReader(`{"trans_type":"en2zh","source":"snoopy"}`)
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", "zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7")
req.Header.Set("app-name", "xy")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "784ac192abb9cce5d326768950e7ce59")
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", `"Google Chrome";v="113", "Chromium";v="113", "Not-A.Brand";v="24"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
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/113.0.0.0 Safari/537.36")
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)
}
这段代码首先创建了一个 HTTP 的服务端对象,把之前的 request payload(字符串格式)转成流,然后用这个流数据创建请求。因为有的时候 payload 会很复杂,一下子放进去需要很大一块内存,然后这样流式处理占用的内存小。底下有很多的请求头设置,这和 cURL 命令以及之前抓包的结果是一样的,有些请求头其实删掉也不影响结果。直到 resp, err := client.Do(req) 这里才是发起了请求。这里的异常处理就包括断网,或者代理设置不对,或者 DNS 出问题没找到这个网址等等。之前我不是在折腾代理吗,就是为了避免这里更麻烦。要确保这个程序是在一个已经走了浏览器代理的命令行里运行的,不然这里也会报错。没报错就是拿到响应了,然后需要 defer resp.Body.Close() 防止 Body 这个流泄露,defer 是在函数结束以后从下往上触发的。最后的代码就是把流再转换回字符串格式,这样才能打印出来和之前的结果对比。
下面是直接用 cURL 命令和等效代码的运行结果对比:
生成的 Go 代码也没有修改直接就可以用,返回的 JSON 是一样的。