Go 语言实战案例——在线词典

86 阅读4分钟

Go 语言实战案例——在线词典

本次案例的目的是演示一个使用命令行参数和用户输入的方式进行词典查询的简单程序。 通过这个案例,可以学习如何使用命令行参数和用户输入的方式来获取程序的输入,以及如何将输入传递给其他函数进行相应的处理。同时,也展示了如何根据不同的输入情况进行条件判断和逻辑处理。

抓包在线翻译网站

  • 访问https://fanyi.caiyunapp.com/#/,在浏览器控制台中选择以cURL格式复制

Pasted image 20230801171718.png

生成HTTP参数

  1. 粘贴到https://curlconverter.com/go/中生成http请求代码
package main  
  
import (  
   "fmt"  
   "io"   "log"   "net/http"   "strings")  
  
func main() {  
   client := &http.Client{}  
   var data = strings.NewReader(`{"trans_type":"en2zh","source":"bad"}`)  
   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-CN,zh;q=0.9")  
   req.Header.Set("app-name", "xy")  
   req.Header.Set("content-type", "application/json;charset=UTF-8")  
   req.Header.Set("device-id", "5f06403c7653bcb11729d8fd1b55cba9")  
   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", `"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"`)  
   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/114.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)  
}

Pasted image 20230801172004.png

  1. 运行生成的代码会打印出返回的JSON格式 Pasted image 20230801172343.png

通过变量输入参数

修改参数

  1. 请求参数结构体
type DictRequest struct {  
   TransType string `json:"trans_type"`  
   Source    string `json:"source"`  
   UserID    string `json:"user_id"`  
}
  1. 修改生成的HTTP请求代码
client := &http.Client{}  
request := DictRequest{TransType: "en2zh", Source: "Bad"}  
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)  
}

解析响应

  1. 复制运行结果到https://oktools.net/json2go中转换成结构体 Pasted image 20230801180446.png

  2. 复制转换的结构体到代码中

type DictRequest struct {  
   TransType string `json:"trans_type"`  
   Source    string `json:"source"`  
   UserID    string `json:"user_id"`  
}  
  
type DictResponse struct {  
   Rc         int        `json:"rc"`  
   Wiki       Wiki       `json:"wiki"`  
   Dictionary Dictionary `json:"dictionary"`  
}  
type Wiki struct {  
}  
type Prons struct {  
   EnUs string `json:"en-us"`  
   En   string `json:"en"`  
}  
type Dictionary struct {  
   Prons        Prons         `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"`  
}
  1. 修改输出代码fmt.Printf("%s\n", bodyText)为以下代码
var dictResponse DictResponse  
err = json.Unmarshal(bodyText, &dictResponse)  
if err != nil {  
   log.Fatal(err)  
}  
fmt.Printf("%#v\n", dictResponse)

Pasted image 20230801180745.png

  1. 运行结果

Pasted image 20230801180815.png

优化完善代码

  1. 修改打印返回结果,通过for循环遍历词典结构体
// fmt.Printf("%#v\n", dictResponse)  
  
// 输出词典信息  
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)  
for _, item := range dictResponse.Dictionary.Explanations {  
   fmt.Println(item)  
}
  1. 创建query函数,把main函数中所有代码封装到query函数,将request的初始化方式从静态的字符串值改为变量word,以便用户输入的单词传递给query函数中的请求对象 Pasted image 20230801190928.png

  2. main函数修改为通过用户输入参数调用query函数,打印返回结构

func main() {  
   var word string  
  
   // 检查命令行参数的数量  
   if len(os.Args) != 2 {  
      fmt.Print("请输入单词:")  
      _, _ = fmt.Scanln(&word)  
   } else {  
      word = os.Args[1]  
   }  
  
   // 调用词典查询  
   query(word)  
}

Pasted image 20230801191420.png

完整代码

package main  
  
import (  
   "bytes"  
   "encoding/json"   "fmt"   "io"   "log"   "net/http"   "os")  
  
// DictRequest 定义了查询词典的请求结构体  
type DictRequest struct {  
   TransType string `json:"trans_type"`  
   Source    string `json:"source"`  
   UserID    string `json:"user_id"`  
}  
  
// DictResponse 定义了词典查询的响应结构体  
type DictResponse struct {  
   Rc         int        `json:"rc"`  
   Wiki       Wiki       `json:"wiki"`  
   Dictionary Dictionary `json:"dictionary"`  
}  
  
// Wiki 定义了维基百科相关的信息  
type Wiki struct {  
}  
  
// Prons 定义了单词的发音相关信息  
type Prons struct {  
   EnUs string `json:"en-us"`  
   En   string `json:"en"`  
}  
  
// Dictionary 定义了词典的详细信息  
type Dictionary struct {  
   Prons        Prons         `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"`  
}  
  
// query 函数用于查询单词的词典信息  
func query(word string) {  
   client := &http.Client{}  
  
   // 创建 DictRequest 对象  
   // request := DictRequest{TransType: "en2zh", Source: "Bad"}  
   request := DictRequest{TransType: "en2zh", Source: word}  
   buf, err := json.Marshal(request)  
   if err != nil {  
      log.Fatal(err)  
   }  
   data := bytes.NewReader(buf)  
  
   // 创建 HTTP 请求  
   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-CN,zh;q=0.9")  
   req.Header.Set("app-name", "xy")  
   req.Header.Set("content-type", "application/json;charset=UTF-8")  
   req.Header.Set("device-id", "5f06403c7653bcb11729d8fd1b55cba9")  
   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", `"Not.A/Brand";v="8", "Chromium";v="114", "Google Chrome";v="114"`)  
   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/114.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)  
   }  
  
   // 检查响应状态码  
   if resp.StatusCode != 200 {  
      log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))  
   }  
  
   // 解析响应内容为 DictResponse 对象  
   var dictResponse DictResponse  
   err = json.Unmarshal(bodyText, &dictResponse)  
   if err != nil {  
      log.Fatal(err)  
   }  
  
   // fmt.Printf("%#v\n", dictResponse)  
  
   // 输出词典信息  
   fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)  
   for _, item := range dictResponse.Dictionary.Explanations {  
      fmt.Println(item)  
   }  
}  
  
func main() {  
   var word string  
  
   // 检查命令行参数的数量  
   if len(os.Args) != 2 {  
      fmt.Print("请输入单词:")  
      _, _ = fmt.Scanln(&word)  
   } else {  
      word = os.Args[1]  
   }  
  
   // 调用词典查询  
   query(word)  
}