GO语言工程实践| 豆包MarsCode AI刷题

95 阅读6分钟

Go 语言基础代码分析与笔记

一、猜数游戏分析

1.1 功能概述

猜数游戏的目标是通过命令行输入,玩家需要猜一个随机生成的数字,程序会根据玩家的猜测给出提示,直到玩家猜对为止。

1.2 代码结构

代码的整体结构比较简单,主要包含以下部分:

  • 随机数的生成
  • 用户输入的获取
  • 用户输入的验证和提示
  • 程序的循环执行直到猜对为止

1.3 代码解析

package main

import (
	"bufio"
	"fmt"
	"math/rand"
	"os"
	"strconv"
	"strings"
	"time"
)
包导入部分
  • bufio: 用于从标准输入读取数据。
  • fmt: 用于格式化输出和打印信息。
  • math/rand: 用于生成随机数。
  • os: 用于操作系统相关的功能,如文件操作、环境变量等。
  • strconv: 用于类型转换,比如字符串与整数之间的转换。
  • strings: 提供了字符串处理相关的函数,如去除空格和换行符。
  • time: 用于时间和日期操作,在这里用于生成基于当前时间的随机数种子。
func main() {
	maxNum := 100
	rand.Seed(time.Now().UnixNano())
	secretNumber := rand.Intn(maxNum)
	// fmt.Println("The secret number is ", secretNumber)
随机数的生成
  • maxNum := 100: 定义了一个常量 maxNum,用于表示猜测数字的上限(0 到 99之间的整数)。
  • rand.Seed(time.Now().UnixNano()): 使用当前的时间戳作为种子初始化随机数生成器,确保每次运行程序生成的随机数不同。
  • secretNumber := rand.Intn(maxNum): 生成一个 0 到 maxNum-1(即 0 到 99)之间的随机整数,作为用户要猜的秘密数字。
	fmt.Println("Please input your guess")
	reader := bufio.NewReader(os.Stdin)
提示用户输入
  • fmt.Println("Please input your guess"): 输出提示信息,告知用户输入他们的猜测。
  • reader := bufio.NewReader(os.Stdin): 创建一个新的 bufio.Reader,用于从标准输入读取数据。
	for {
		input, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("An error occured while reading input. Please try again", err)
			continue
		}
		input = strings.Trim(input, "\r\n")
用户输入循环
  • for {}: 一个无限循环,程序会一直运行直到用户猜对数字为止。
  • input, err := reader.ReadString('\n'): 从标准输入读取用户输入的数据,直到遇到换行符 \n。如果读取错误,打印错误信息并继续下一次循环。
  • input = strings.Trim(input, "\r\n"): 去除用户输入中的换行符和回车符,确保输入的纯净。
		guess, err := strconv.Atoi(input)
		if err != nil {
			fmt.Println("Invalid input. Please enter an integer value")
			continue
		}
输入验证
  • guess, err := strconv.Atoi(input): 将用户输入的字符串转换为整数。如果转换失败(即输入的不是有效的整数),则进入 err 分支,提示用户重新输入。
		fmt.Println("You guess is", guess)
		if guess > secretNumber {
			fmt.Println("Your guess is bigger than the secret number. Please try again")
		} else if guess < secretNumber {
			fmt.Println("Your guess is smaller than the secret number. Please try again")
		} else {
			fmt.Println("Correct, you Legend!")
			break
		}
	}
}
猜测判断与提示
  • fmt.Println("You guess is", guess): 打印用户输入的猜测。

  • 判断猜测是否正确:

    • 如果猜测大于秘密数字,提示猜测数字大了。
    • 如果猜测小于秘密数字,提示猜测数字小了。
    • 如果猜测正确,打印成功信息并跳出循环 break
总结

该游戏是通过一个循环不断接受用户的输入,并根据猜测给出反馈,直到用户猜对数字。程序中使用了bufio进行输入处理,使用strconv进行类型转换,且每次用户输入后,都会根据输入与随机数进行对比,并给出相应的提示。


二、命令行词典代码分析

2.1 功能概述

该部分代码实现了一个查询词典的功能,用户通过命令行传入一个英文单词,程序会通过 API 请求查询该单词的相关信息,并展示其发音、解释和词义等内容。

2.2 代码结构

代码的主要结构包括:

  • 定义请求和响应的结构体
  • 通过 HTTP 请求调用外部 API
  • 解析 API 返回的数据
  • 格式化输出查询结果

2.3 代码解析

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
)
包导入部分
  • bytes: 提供了处理字节切片的函数,常用于处理请求和响应的内容。
  • encoding/json: 用于解析和生成 JSON 数据。
  • fmt: 格式化输出和打印信息。
  • ioutil: 提供了文件和 I/O 操作的工具函数,这里用于读取 HTTP 响应的主体。
  • log: 用于日志记录和错误处理。
  • net/http: 提供了 HTTP 客户端和服务端的功能,这里用于发起请求和获取响应。
  • os: 提供了操作系统相关的功能,这里用于读取命令行参数。
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 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"`
}
请求与响应结构体
  • DictRequest:用于构建请求的结构体,包含了翻译类型、源单词和用户ID(虽然在此示例中未使用 user_id)。
  • DictResponse:用于接收 API 响应的结构体,结构体内包含了从 API 返回的各个字段,如发音、词义、同义词、反义词等。
func query(word string) {
	client := &http.Client{}
	request := DictRequest{TransType: "en2zh", Source: word}
	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)
	}
请求构建与发送
  • client := &http.Client{}: 创建一个 HTTP 客户端对象,用于发送请求。
  • request := DictRequest{TransType: "en2zh", Source: word}: 构建请求体,设置翻译类型为从英文到中文,源单词为用户传入的单词。
  • `buf, err := json.Marshal(request)

`: 将请求体序列化为 JSON 格式的字节流。

  • req, err := http.NewRequest("POST", ...): 构造 HTTP POST 请求,指定请求的 URL 和请求体。
	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)
	}
	if resp.StatusCode != 200 {
		log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
	}
响应处理
  • resp, err := client.Do(req): 发送请求并获取响应。
  • defer resp.Body.Close(): 确保响应体在函数执行完后被关闭,释放资源。
  • bodyText, err := ioutil.ReadAll(resp.Body): 读取响应的主体内容。
  • if resp.StatusCode != 200: 检查响应的状态码,如果不是 200(表示成功),则输出错误信息。
	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)
	}
解析 JSON 响应并输出
  • var dictResponse DictResponse: 声明一个 DictResponse 变量,用于存储解析后的响应数据。
  • err = json.Unmarshal(bodyText, &dictResponse): 将响应的 JSON 数据反序列化到 dictResponse 变量中。
  • 打印单词的发音、同义词、解释等内容。
func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
		`)
		os.Exit(1)
	}
	word := os.Args[1]
	query(word)
}
主函数
  • 检查命令行参数是否正确,若用户未提供单词,则输出用法信息并退出。
  • 获取命令行参数中的单词并调用 query 函数查询其相关信息。

总结

这篇笔记对两个 Go 语言示例进行了详细分析,第一个是一个经典的猜数游戏,使用了 Go 的基本输入输出功能、随机数生成和条件判断。第二个示例是一个通过 API 查询词典的程序,涉及了 HTTP 请求的构建与发送、JSON 的解析与处理。