Go语言实战及课后作业 | 青训营

65 阅读9分钟

目录

猜数字

在线词典

本篇笔记主要是关于Go语言的实战部分,以及关于这部分的课后作业,在下可能有写的不好的地方,不足之处还望大家批评指正。好了,下面进入正题。

猜数字

题目顾名思义,就是系统在一定范围内随便给一个隐藏的数字,玩家通过输入一个数字,程序通过判断比给定的数字大还是小予以提示,错误则让玩家继续猜,正确则返回胜利标识。大致的执行效果如图所示。

QQ图片20230730223304.png

要实现这个游戏,我们首先要先生成一个范围内的随机数。这里要用到rand包。初步代码如下:

maxNum := 100
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)

通过调试我们会发现它一直输出同一数字,通过查阅官方文档我们知道,这个包在使用前要设置随机数种子,否则会一直生成相同的随机数。由此我们自然联想到可以通过不同时间给予不同的随机数来设置,因此修改生成代码如下。

maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)

通过简单调试发现符合要求,随机数生成成功。下一步我们要做的是获取玩家的输入,在老师予以我们的ppt中,我们可以看到ppt里给的方法如下所示。

fmt.Println("Please input your guess")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
	fmt.Println("An error occured while reading input. Please try again", err)
}
input = strings.Trim(input, "\r\n")
guess, err := strconv.Atoi(input)
if err != nil {
	fmt.Println("Invalid input. Please enter an integer value")
}
fmt.Println("You guess is", guess)

其中用到的几个包及其方法需要解释一下。 在这段获取输入的代码中,用到了bufio、strings、strconv、os包。bufio包是实现内置缓冲区的I/O操作,bufio.NewReader是一种快读操作,而os.Stdin则是指向标准输入文件的指针,因此reader变量便是一个读取标准输入得到的量;而下面的input则是读取一行操作;strings包中的函数主要用于对字符串进行操作,其Trim方法是从外到内去除所传入的字符;strconv常用于字符串与其他类型之间的转换,代码中strconv.Atoi操作用于将字符类型转换为int类型。代码用这样的方式读取输入,并将读取的字符串转为整型数字。

完成读取输入后,便是实现判断逻辑,话不多说上代码。

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
}

最后要实现循环操作,因此要将他放入一个循环结构中。完整代码如下

package main

import (
   "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)

   fmt.Println("Please input your guess")
   reader := bufio.NewReader(os.Stdin)
   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")

   	guess, err := strconv.Atoi(input)
   	if err != nil {
   		fmt.Println("Invalid input. Please enter an integer value")
   		continue
   	}
   	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
   	}
   }
}

在课后作业中,要求我们用scanf方法简化代码,通过查询官方文档,我们知道scanf可以直接获取终端输入,相比于之前代码繁琐的获取输入流程,用scanf可以大大简化,故而用scanf的方法的代码如下所示。

package main

import (
   "fmt"
   "math/rand"
   "time"
)

func main() {
   maxNum := 100
   rand.Seed(time.Now().UnixNano())
   secretNumber := rand.Intn(maxNum)
   //fmt.Println("The secret number is", secretNumber)
   var input int
   fmt.Println("please input your guess")
   for {
   	fmt.Scanf("%d", &input)
   	fmt.Println("you guess is", input)
   	if input > secretNumber {
   		fmt.Println("your guess is bigger than the secret number,please try again")
   	} else if input < secretNumber {
   		fmt.Println("your guess is smaller than the secret number,please try again")
   	} else {
   		fmt.Println("Correct")
   		break
   	}
   }
}

由上述代码可以显而易见地看出代码量和用到的包都明显小于第一段代码,可见是一个正向的优化。

在线词典

在线词典是一个很有意思的题目,其中用到的一些方法在实际代码编写中十分有用,因此在这里予以记录,也是对用到的方法的一些总结。

首先对要使用的翻译网站进行抓包,这里采用的是谷歌浏览器以及彩云小译翻译网站,在网页中输入一个单词,后右键-检查,打开浏览器的开发者工具,然后点翻译进行抓包。如图所示,这里的dict字段即是翻译得到的结果。

QQ图片20230731101009.png

其中payload中的source是要翻译的单词,而trans_type部分是翻译类型。接下来对该字段copy它的curl。

QQ图片20230731101649.png

接着打开网站:curlconverter.com/go/ ,把复制好的curl写入框中,会自动生成go代码。

QQ图片20230731101910.png

这样抓包部分就完成了,接着便是改写结构体,把返回的json反序列化到结构体内,这里用到的工具是json生成结构体工具:oktools.net/json2go

QQ图片20230731102221.png

将生成的代码copy到代码编辑器中,观察我们需要的翻译的结构字段,从代码中可以看出在下述结构体中。

Dictionary struct {
		Prons struct {
			EnUs string `json:"en-us"`
			En   string `json:"en"`
		} `json:"prons"`
}`json:""dictonary`

最关键的两个步骤完成,接着便是完善代码,最终版彩云小译词典代码如下:

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/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 {
	} `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"`
}

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)
	}
	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", "abe8e74b023bea38ffaa239ad05aa420")
	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="99", "Google Chrome";v="115", "Chromium";v="115"`)
	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/115.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))
	}
	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)
	}
}
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)
}

最终执行结果如图。

QQ图片20230731102814.png

课后作业中要求增加另一个翻译软件的支持,这里选用的是百度翻译,直接上代码。

package main

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
)

type DictRequest struct {
	Query  string `json:"query"`
	UserID string `json:"user_id"`
}

type DictResponse struct {
	TransResult struct {
		Data []struct {
			Dst string `json:"dst"`
			Src string `json:"src"`
		} `json:"data"`
		From     string `json:"from"`
		To       string `json:"to"`
		Status   int    `json:"status"`
		Type     int    `json:"type"`
		Phonetic []struct {
			SrcStr string `json:"src_str"`
			TrgStr string `json:"trg_str"`
		} `json:"phonetic"`
	} `json:"trans_result"`
	DictResult struct {
		Edict struct {
			Item []struct {
				TrGroup []struct {
					Tr          []string      `json:"tr"`
					Example     []interface{} `json:"example"`
					SimilarWord []string      `json:"similar_word"`
				} `json:"tr_group"`
				Pos string `json:"pos"`
			} `json:"item"`
			Word string `json:"word"`
		} `json:"edict"`
		From        string `json:"from"`
		SimpleMeans struct {
			WordName  string   `json:"word_name"`
			From      string   `json:"from"`
			WordMeans []string `json:"word_means"`
			Exchange  struct {
				WordPl  []string `json:"word_pl"`
				WordEst []string `json:"word_est"`
				WordEr  []string `json:"word_er"`
			} `json:"exchange"`
			Tags struct {
				Core  []string `json:"core"`
				Other []string `json:"other"`
			} `json:"tags"`
			Symbols []struct {
				PhEn  string `json:"ph_en"`
				PhAm  string `json:"ph_am"`
				Parts []struct {
					Part  string   `json:"part"`
					Means []string `json:"means"`
				} `json:"parts"`
				PhOther string `json:"ph_other"`
			} `json:"symbols"`
		} `json:"simple_means"`
		Common struct {
			Text string `json:"text"`
			From string `json:"from"`
		} `json:"common"`
		Collins struct {
			Entry []struct {
				EntryID string `json:"entry_id"`
				Type    string `json:"type"`
				Value   []struct {
					MeanType []struct {
						InfoType string `json:"info_type"`
						InfoID   string `json:"info_id"`
						Example  []struct {
							ExampleID string `json:"example_id"`
							TtsSize   string `json:"tts_size"`
							Tran      string `json:"tran"`
							Ex        string `json:"ex"`
							TtsMp3    string `json:"tts_mp3"`
						} `json:"example"`
					} `json:"mean_type"`
					Gramarinfo []interface{} `json:"gramarinfo"`
					Tran       string        `json:"tran"`
					Def        string        `json:"def"`
					MeanID     string        `json:"mean_id"`
					Posp       []struct {
						Label string `json:"label"`
					} `json:"posp"`
				} `json:"value"`
			} `json:"entry"`
			WordName      string `json:"word_name"`
			Frequence     string `json:"frequence"`
			WordEmphasize string `json:"word_emphasize"`
			WordID        string `json:"word_id"`
		} `json:"collins"`
		Lang   string `json:"lang"`
		Oxford struct {
			Entry []struct {
				Tag  string `json:"tag"`
				Name string `json:"name"`
				Data []struct {
					Tag  string `json:"tag"`
					Data []struct {
						Tag   string `json:"tag"`
						P     string `json:"p"`
						PText string `json:"p_text"`
					} `json:"data"`
				} `json:"data"`
			} `json:"entry"`
			Unbox []struct {
				Tag  string `json:"tag"`
				Type string `json:"type"`
				Name string `json:"name"`
				Data []struct {
					Tag     string   `json:"tag"`
					Text    string   `json:"text,omitempty"`
					Words   []string `json:"words,omitempty"`
					Outdent string   `json:"outdent,omitempty"`
					Data    []struct {
						Tag    string `json:"tag"`
						EnText string `json:"enText"`
						ChText string `json:"chText"`
					} `json:"data,omitempty"`
				} `json:"data"`
			} `json:"unbox"`
		} `json:"oxford"`
		Sanyms []struct {
			Tit  string `json:"tit"`
			Type string `json:"type"`
			Data []struct {
				P string   `json:"p"`
				D []string `json:"d"`
			} `json:"data"`
		} `json:"sanyms"`
		Usecase struct {
			Idiom []struct {
				P    string `json:"p"`
				Tag  string `json:"tag"`
				Data []struct {
					Tag  string `json:"tag"`
					Data []struct {
						EnText string `json:"enText"`
						Tag    string `json:"tag"`
						ChText string `json:"chText"`
						Before []struct {
							Tag  string `json:"tag"`
							Data []struct {
								EnText string `json:"enText"`
								Tag    string `json:"tag"`
								ChText string `json:"chText"`
							} `json:"data"`
						} `json:"before,omitempty"`
					} `json:"data"`
				} `json:"data"`
			} `json:"idiom"`
		} `json:"usecase"`
		BaiduPhrase []struct {
			Tit   []string `json:"tit"`
			Trans []string `json:"trans"`
		} `json:"baidu_phrase"`
		QueryExplainVideo struct {
			ID           int    `json:"id"`
			UserID       string `json:"user_id"`
			UserName     string `json:"user_name"`
			UserPic      string `json:"user_pic"`
			Query        string `json:"query"`
			Direction    string `json:"direction"`
			Type         string `json:"type"`
			Tag          string `json:"tag"`
			Detail       string `json:"detail"`
			Status       string `json:"status"`
			SearchType   string `json:"search_type"`
			FeedURL      string `json:"feed_url"`
			Likes        string `json:"likes"`
			Plays        string `json:"plays"`
			CreatedAt    string `json:"created_at"`
			UpdatedAt    string `json:"updated_at"`
			DuplicateID  string `json:"duplicate_id"`
			RejectReason string `json:"reject_reason"`
			CoverURL     string `json:"coverUrl"`
			VideoURL     string `json:"videoUrl"`
			ThumbURL     string `json:"thumbUrl"`
			VideoTime    string `json:"videoTime"`
			VideoType    string `json:"videoType"`
		} `json:"queryExplainVideo"`
	} `json:"dict_result"`
	LijuResult struct {
		Double string   `json:"double"`
		Tag    []string `json:"tag"`
		Single string   `json:"single"`
	} `json:"liju_result"`
	Logid int64 `json:"logid"`
}

func query(word string) {
	client := &http.Client{}
	request := DictRequest{Query: word}
	buf, err := json.Marshal(request)
	if err != nil {
		log.Fatal(err)
	}
	var data = bytes.NewReader(buf)
	req, err := http.NewRequest("POST", "https://fanyi.baidu.com/v2transapi?from=en&to=zh", data)
	if err != nil {
		log.Fatal(err)
	}
	req.Header.Set("Accept", "*/*")
	req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
	req.Header.Set("Acs-Token", "1690724350615_1690724363864_GWtqrTK4w25n2L8OLV79AUI0Rz9QYmTEqfOypU3M8HhT+jANdLB+Qc0u8y3OkDlGcNvUHF9ktBN/oHhO0e6GiilCTIviZjWpWtUIx4Ze3fxbmuktA/TkyA9qp99dldVbApqyg8ACaLI4PO0UUNuoormocqTxT5yweMEe5LrnpMsrwi5I2h1ZkYkYS8QKkNpZb2QOOOjHaA37br9zzwmH8wxv3aT57TK+sPlpp2uS19awkIvRkHPJ+bwPS4ylFjdO0rk45MzkbJ0EvlBu3MVITg/8q079gKragEBwX9LubalrlncAn55W3tDfkGQQ9QMA6SyhkTcR2OM41cpicaCjfJly/Ct2XOkitBfqS+/PdluJ+kzWRJq+xW8wUeD4cDHc6AgupXveaYKncj0zvNC5+X/6CVxfN6F90qYWe5A97l8gOr2gmnHSic//Q1rWrOuKzJ/wgLSmVzhjQUJUZryDkkc9QwONtzVHocJWePiquXBFyKoazRRNgcYTworEuJnn")
	req.Header.Set("Connection", "keep-alive")
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
	req.Header.Set("Cookie", "BIDUPSID=C74DF6309C57E0A86BADD79F87D1E83A; PSTM=1683682473; BAIDUID=C74DF6309C57E0A89440C4491DA03A12:FG=1; BDORZ=B490B5EBF6F3CD402E515D22BCDA1598; REALTIME_TRANS_SWITCH=1; FANYI_WORD_SWITCH=1; HISTORY_SWITCH=1; SOUND_SPD_SWITCH=1; SOUND_PREFER_SWITCH=1; BA_HECTOR=850h01a42h0k248k012g00av1iccbft1o; BAIDUID_BFESS=C74DF6309C57E0A89440C4491DA03A12:FG=1; PSINO=3; delPer=0; H_PS_PSSID=36557_39106_38879_39114_39037_38918_39088_26350_39132_39051_22160_39100_39043_38953; Hm_lvt_64ecd82404c51e03dc91cb9e8c025574=1690708541,1690724350; Hm_lpvt_64ecd82404c51e03dc91cb9e8c025574=1690724350; ab_sr=1.0.1_NjQ4YzYzYWE2NmM0ZTFmYWY1NDE0ZDAyYjE1MGVkNzEwNjNlZmVkNGE2YTQyNGQwZWQzNTY2NTlkZTY3MTA4NzkxZjIwN2MzMTBkOWIxYmQ3YjEwZDJjYWQwNTI1OTljYThmYmI1MTdiZjQ5MzE4Y2IwMTk4OTRiZWFiMzc5ZWU5NjAyYTY1ZTEzMDhhYzE1OTZlYzljYTVhMWQyNjg1OA==")
	req.Header.Set("Origin", "https://fanyi.baidu.com")
	req.Header.Set("Referer", "https://fanyi.baidu.com/?aldtype=16047")
	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/115.0.0.0 Safari/537.36")
	req.Header.Set("X-Requested-With", "XMLHttpRequest")
	req.Header.Set("sec-ch-ua", `"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"`)
	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.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))
	}
	var dictResponse DictResponse
	err = json.Unmarshal(bodyText, &dictResponse)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Println(word, "UK:", dictResponse.DictResult.SimpleMeans.Symbols, "US:", dictResponse.DictResult.SimpleMeans.Symbols)
	for _, item := range dictResponse.DictResult.SimpleMeans.WordMeans {
		fmt.Println(item)
	}
}
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)
}

课后作业第三个任务要求并行请求来提高响应速度,这里不是很理解并行请求的意思,自己的理解是将前两个翻译软件的代码打包,然后另外写一个主函数直接调用,不知道这样理解对不对,还望各位指正。