GO语言工程实践课后作业:实现思路、代码以及路径记录(1) | 豆包MarsCode AI刷题

78 阅读5分钟

本文主要内容为实现《GO语言实战案例》课程课后作业,主要展示个人思路,代码以及部分思考,主要内容为解决问题思路及其代码。
如有错误,希望多多指教。

课后作业要求

  1. 修改第一个例子猜谜游戏里面的最终代码,使用fmt.Scanf来简化代码实现
  2. 修改第二个例子命令行词典里面的最终代码,增加另一种翻译引擎的支持
  3. 在上一步骤的基础上,修改代码实现并行请求两个翻译引擎来提高响应速度

前期准备

  1. 开发环境
  • 开发环境:WSL;
  • 操作系统:Ubuntu;
  • 代码编辑器:VSCode。
  1. 代码库准备:使用git clone [repository-url]命令克隆代码库至本地开发环境;

1.修改第一个例子猜谜游戏里面的最终代码,使用fmt.Scanf来简化代码实现

查询fmt.Scanf()方法相关文档说明:fmt package - fmt - Go Packages

左侧目录选择FunctionsScanf(format,a),即可看到以下说明。

func Scanf(format string, a ...any) (n int, err error)

Scanf scans text read from standard input, storing successive space-separated values into successive arguments as determined by the format. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why. Newlines in the input must match newlines in the format. The one exception: the verb %c always scans the next rune in the input, even if it is a space (or tab etc.) or newline.

意思大概是Scanf返回成功扫描数量和err,输入中必须有换行符来匹配,但是要注意的是,%c扫描输入的下一个; 知道方法下面的修改就很容易了,代码具体如下(代码确实简化不少):

func main() {
	var maxNum = 100 //设置最大数字
	secretNum := rand.Intn(maxNum)	//随机生成secretNum
	fmt.Println("Please input your guess:")
	var guessNum int
	for {
		_, err := fmt.Scanf("%d\n", &guessNum)//这里使用Scanf代替
		if err != nil {
			fmt.Println("Invalid input. Please enter an integer value")
			continue
		}
		if guessNum > secretNum {
			fmt.Println("Your guess is bigger than the secret number. Please try again")
		} else if guessNum < secretNum {
			fmt.Println("Your guess is smaller than the secret number. Please try again")
		} else {
			fmt.Println("Correct, you Legend!")
			break
		}
	}
}

2. 修改第二个例子命令行词典里面的最终代码,增加另一种翻译引擎的支持

步骤参照课程所讲方法,借助Convert curl commands to GoJSON转Golang Struct - 在线工具 - OKTools(注意:这个和课上资料里显示的网址不太一样,课上的网址我没有成功打开)解析JSON,这里我一开始选用的是百度翻译,但是做到定义响应结构体的时候,没有找到对应相关的json文件,最后重新找相关搜索引擎,最后选用的是火山翻译,为了增加对火山翻译引擎的支持,我们首先需要定义请求和响应的结构体。具体代码如下:

type DictRequest2 struct{
	source_language string `json:"source_language"`
	target_language string `json:"target_language"`
	text string `json:"text"`
	home_language string `json:"home_language"`
	category string `json:"category"`
	glossary_list []string `json:"glossary_list"`
	enable_user_glossary bool `json:"enable_user_glossary"`
}

type DictResponse2 struct {
	Translation string `json:"translation"`
	DetectedLanguage string `json:"detected_language"`
	Probability int `json:"probability"`
	BaseResp struct {
		StatusCode int `json:"status_code"`
		StatusMessage string `json:"status_message"`
	} `json:"base_resp"`
}

func query2(word string) {
	client := &http.Client{}
	request := DictRequest2{
		source_language: "detect",
		target_language: "zh",
		text: word,
		home_language: "zh",
		category: "",
		glossary_list: []string{},
		enable_user_glossary: false,
	}
	buf,err := json.Marshal(request)
	if err !=nil{
		log.Fatal(err)
	}
	var data = bytes.NewReader(buf)
	req, err := http.NewRequest("POST", "https://translate.volcengine.com/web/translate/v1/?msToken=&X-Bogus=DFSzswVLQDVrMhMWtKAK1pN1442d&_signature=_02B4Z6wo00001SDdypAAAIDCtfIJ-NsBVgkg3c4AAC8HlnaJnHXNdfzAgeUFi-JeladfEVqINGnIpCWWKb8sAyKcrY5wqrQtf1krBgfTkPNVaAA-jC.hFtbL3swanaMaog3wPGg-QT9d-xrq19", data)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "application/json, text/plain, */*")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
	req.Header.Set("Cache-Control", "no-cache")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Content-Type", "application/json")
	req.Header.Set("Cookie", "monitor_huoshan_web_id=5760560216414852360; hasUserBehavior=1; csrfToken=8b13c7ddf17a645320fff792b453c01c; csrfToken=8b13c7ddf17a645320fff792b453c01c; ve_doc_history=4640; referrer_title=%E4%BA%A7%E5%93%81%E8%AE%A1%E8%B4%B9--%E6%9C%BA%E5%99%A8%E7%BF%BB%E8%AF%91-%E7%81%AB%E5%B1%B1%E5%BC%95%E6%93%8E; VOLCFE_im_uuid=1731399887599911556; __tea_cache_tokens_3569={%22web_id%22:%227436305811683051019%22%2C%22user_unique_id%22:%227436305811683051019%22%2C%22timestamp%22:1731399887611%2C%22_type_%22:%22default%22}; isIntranet=0; monitor_session_id_flag=1; i18next=zh-CN; s_v_web_id=verify_m3e9laj9_9HW1CVxK_cz6U_4Sti_9af5_LA5x0aZijbNZ; ttcid=849740ea8ea745b2a086e39773359a0e29; tt_scid=b1QYzTzAyQQa8sJodTw810pr5WrmjiV02zga5n7A81wFnpbxaPRbRmE4pwjtprWhf718")
	req.Header.Set("Origin", "https://translate.volcengine.com")
	req.Header.Set("Pragma", "no-cache")
	req.Header.Set("Referer", "https://translate.volcengine.com/mobile?category=&home_language=zh&source_language=detect&target_language=zh&text=fun")
	req.Header.Set("Sec-Fetch-Dest", "empty")
	req.Header.Set("Sec-Fetch-Mode", "cors")
	req.Header.Set("Sec-Fetch-Site", "same-origin")
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0")
	req.Header.Set("sec-ch-ua", `"Chromium";v="130", "Microsoft Edge";v="130", "Not?A_Brand";v="99"`)
	req.Header.Set("sec-ch-ua-mobile", "?0")
	req.Header.Set("sec-ch-ua-platform", `"Windows"`)
	resp, err := client.Do(req)
    if err != nil {
        log.Fatalf("Failed to send request: %v", err)
    }
    defer resp.Body.Close()
    // 检查响应体是否为空
    if resp.ContentLength == 0 {
        log.Fatal("Response body is empty")
    }
    bodyText, err := io.ReadAll(resp.Body)
    if err != nil {
        log.Fatalf("Failed to read response body: %v", err)
    }
    // 打印原始响应体文本
    fmt.Println("Raw response body:", string(bodyText))
    if resp.StatusCode != http.StatusOK {
        log.Fatalf("Bad StatusCode: %d, body: %s", resp.StatusCode, string(bodyText))
    }
    // 检查 JSON 数据是否有效
    if !json.Valid(bodyText) {
        log.Fatal("Invalid JSON data: %s", string(bodyText))
    }
    var dictResponse2 DictResponse2
    err = json.Unmarshal(bodyText, &dictResponse2)
    if err != nil {
        log.Fatalf("Failed to unmarshal response: %v", err)
    }
    fmt.Println(word, "Translation:", dictResponse2.Translation)
}

但不知道为什么query2()响应为空,后面查询资料,尝试ping translate.volcengine.com,显示可以正常连接,尝试curl -v -X POST "https://translate.volcengine.com/web/translate/v1/..." -H "Content-Type: application/json" -d '{"source_language": "detect", "target_language": "zh", "text": "go", ...}',返回结果显示请求成功发送到了服务器,HTTP状态码为200,但是响应体是空,猜测可能是网站自身机制原因。

3. 在上一步骤的基础上,修改代码实现并行请求两个翻译引擎来提高响应速度

这块并不难,结合课上讲的相关知识点,直接使用channel处理,然后我结合了sync.WaitGroup,优化代码,具体main()函数相关代码如下:

func main() {
	if len(os.Args) != 2 {
		fmt.Fprintf(os.Stderr, `usage: simpleDict WORD example: simpleDict hello`)
		os.Exit(1)
	}
	word := os.Args[1]

	ch := make(chan string, 2)
	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		query(word)
		ch <- "query done"
	}()
	go func() {
		defer wg.Done()
		query2(word)
		ch <- "query2 done"
	}()
	wg.Wait()
}