Go 语言实现简易词典查询 | 豆包MarsCode AI刷题

48 阅读4分钟

1. 项目概述

该项目通过 Go 语言编写一个简易词典查询程序,向第三方 API 发送请求查询单词信息并输出查询结果。用户可以通过命令行输入单词或通过交互方式输入。


2. 项目设计思路

  • 数据结构设计:使用结构体定义请求与响应的数据格式,便于代码维护与操作。
  • 数据转换与序列化:将结构体数据序列化为 JSON 格式,转换为流便于 HTTP 请求传输。
  • HTTP 请求与响应处理:构建 HTTP POST 请求,设置请求头,发送请求并处理响应。
  • 用户交互设计:支持通过命令行输入单词,或在没有输入参数时通过交互方式从控制台获取单词。
  • 错误检查与健壮性:在每个重要步骤中检查错误,防止由于外部条件导致程序崩溃。
  • 结果展示:从响应结果中提取单词发音和解释信息,以用户友好的格式展示。

3. 项目知识点

3.1 结构体定义与 JSON 标签

知识点

  • 结构体:用于定义请求和响应的字段结构。
  • JSON 标签:使用结构体标签 json:"field_name" 将结构体字段映射到 JSON 中的字段,方便编码与解码。

代码示例

type DictRequest struct {
	TransType string `json:"trans_type"`
	Source    string `json:"source"`
	UserID    string `json:"user_id"`
}

type DictResponse struct {
	Rc   int `json:"rc"`
	Dictionary struct {
		Prons struct {
			EnUs string `json:"en-us"`
			En   string `json:"en"`
		} `json:"prons"`
		Explanations []string `json:"explanations"`
	} `json:"dictionary"`
}

注意事项

  • 确保 JSON 标签与 API 响应字段一致,以防止解析错误。
  • 定义字段时尽量使用合适的数据类型,如 string[]string

3.2 数据的序列化与流转换

知识点

  • JSON 序列化:使用 json.Marshal 将结构体数据序列化为 JSON 格式,准备传输。
  • 流转换bytes.NewReader 将序列化的 []byte 转换为 io.Reader,用于构建 HTTP 请求体。

代码示例

request := DictRequest{TransType: "en2zh", Source: "good"}
buf, err := json.Marshal(request)
if err != nil {
	log.Fatal(err)
}
var data = bytes.NewReader(buf) // 转换为 io.Reader 类型

注意事项

  • json.Marshal 返回 []byte,需要将其包装为 io.Reader,便于作为 HTTP 请求体传输。

3.3 HTTP 请求的构建与发送

知识点

  • http.NewRequest:构建 HTTP 请求,指定 URL、请求方法和请求体。
  • 请求头设置:通过 req.Header.Set 设置请求头,确保请求能被 API 接受。
  • HTTP 客户端:通过 http.Client 发送请求并接收响应。

代码示例

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("authorization", "Bearer your_token")
client := &http.Client{}
resp, err := client.Do(req) // 发送请求
if err != nil {
	log.Fatal(err)
}
defer resp.Body.Close()

注意事项

  • 确保设置必要的请求头,以防被 API 拒绝。
  • defer resp.Body.Close() 确保在处理完响应后释放资源。

3.4 处理 HTTP 响应

知识点

  • 读取响应数据:使用 io.ReadAll 从响应体中读取数据,获取 API 返回的 JSON 数据。
  • JSON 解码:使用 json.Unmarshal 将 JSON 数据解析为结构体,便于访问特定字段。
  • 状态码检查:确保返回状态码为 200 表示成功,否则输出错误信息。

代码示例

bodyText, err := io.ReadAll(resp.Body)
if err != nil {
	log.Fatal(err)
}
if resp.StatusCode != 200 {
	log.Fatal("bad StatusCode:", resp.StatusCode)
}
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse) // JSON 解码
if err != nil {
	log.Fatal(err)
}

注意事项

  • 检查 resp.StatusCode,便于及时发现错误请求。
  • 使用 json.Unmarshal 解码时,确保结构体字段与 JSON 响应字段匹配。

3.5 用户输入与交互设计

知识点

  • 命令行参数:使用 os.Args 从命令行获取单词查询参数。
  • 交互式输入:使用 bufio.NewScanner 从控制台获取输入,适用于未提供命令行参数的情况。

代码示例

if len(os.Args) != 2 {
	fmt.Print("请输入要查询的单词:")
	scanner := bufio.NewScanner(os.Stdin)
	if scanner.Scan() {
		word := strings.TrimSpace(scanner.Text())
		query(word)
	} else {
		fmt.Println("未输入有效的单词")
		os.Exit(1)
	}
} else {
	word := os.Args[1]
	query(word)
}

注意事项

  • 使用 strings.TrimSpace 去除输入中的多余空格,避免空白输入导致的错误。
  • 检查输入是否为空,并适当处理无效输入。

3.6 错误处理与日志

知识点

  • 错误处理模式:每个关键步骤后检查 err,及时发现问题并终止程序执行。
  • 日志输出log.Fatal 输出错误信息并终止程序运行,适合严重错误场景。

代码示例

buf, err := json.Marshal(request)
if err != nil {
	log.Fatal("JSON 编码错误:", err)
}

注意事项

  • 在关键的网络请求、文件操作、用户输入等步骤后添加错误检查。
  • log.Fatal 输出错误后自动调用 os.Exit(1),中止程序执行。

3.7 结果展示与格式化输出

  • 在请求完成后,程序从 DictResponse 结构体中提取字段,并以用户友好的方式输出单词的发音和解释信息。

  • 知识点

    • 结构体字段访问:通过 dictResponse.Dictionary.Prons.En 等访问结构体字段,提取信息进行打印。
    • 格式化输出:使用 fmt.Println 打印发音和解释列表等信息,以易于用户阅读的格式展示查询结果。

代码示例

fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, explanation := range dictResponse.Dictionary.Explanations {
	fmt.Println(explanation)
}

注意事项

  • 确保结构体字段和 API 返回的字段一致,以避免访问错误。
  • for 循环遍历解释信息,逐行打印,提升可读性。