GO语言工程实践课后作业:实现思路、代码以及路径记录 | 青训营

72 阅读3分钟

一、猜谜游戏的另一种写法

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

请注意,在使用 fmt.Scanf 读取输入时,我们在格式字符串末尾加上 \n,以便读取并忽略输入中的换行符,确保每次读取都是从新的一行开始。

package main  
  
//猜谜游戏  
import (  
"fmt"  
"math/rand"  
"time"  
)  
  
func main() {  
maxNum := 100  
rand.Seed(time.Now().UnixNano()) //用时间戳来初始化随机数种子  
secretNumber := rand.Intn(maxNum)  
  
fmt.Println("请猜一个1到100之间的整数:")  
var guess int  
for {  
_, err := fmt.Scanf("%d\n", &guess)  
if err != nil {  
fmt.Println("无效的输入,请重新输入整数:")  
continue  
}
  
fmt.Println("You guess is", guess)  
if guess > secretNumber {  
fmt.Println("您的猜测大于该数字,请重试")  
} else if guess < secretNumber {  
fmt.Println("您的猜测小于该数字,请重试")  
} else {  
fmt.Println("猜测正确,你赢了")  
break  
}  
}  
}

二、在线词典的2种翻译引擎写法

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

跟第一种使用了差不多的写法,流程下来都是那一套。但是由于第二个接口的加密,所以暂时无法返回内容,咱没法解决这个问题。

package main  
  
import (  
"encoding/json"  
"fmt"  
"io"  
"io/ioutil"  
"log"  
"net/http"  
"os"  
"strings"  
)  
  
type DictRequest struct {  
TransType string  
Source string  
UserID string  
}  
  
type DictResponse struct {  
//此处省略
}  
  
type DictResponse2 struct {  
//此处省略
}  
  
func query(word string) {  
  
url := "https://api.interpreter.caiyunai.com/v1/dict"  
method := "POST"  
  
payload := strings.NewReader(`{"trans_type":"en2zh","source":"` + word + `"}`)  
  
client := &http.Client{}  
req, err := http.NewRequest(method, url, payload)  
  
if err != nil {  
fmt.Println(err)  
return  
}  

//此处省略
req.Header.Add()
  
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 query_sougo(word string) {  
  
url := "https://fanyi.sogou.com/api/transpc/text/result"  
method := "POST"  
  
payload := strings.NewReader(`{"from":"auto","to":"zh-CHS","text":"` + word + `","client":"pc","fr":"browser_pc","needQc":1,"s":"dccdc10851a31d187d79396e3467e22e","uuid":"a22e67a0-61f5-4844-a668-1cf0f401fdee","exchange":false}`)  
  
client := &http.Client{}  
req, err := http.NewRequest(method, url, payload)  
  
if err != nil {  
fmt.Println(err)  
return  
}  

//此处省略
req.Header.Add()
  
res, err := client.Do(req)  
if err != nil {  
fmt.Println(err)  
return  
}  
defer res.Body.Close()  
  
body, err := ioutil.ReadAll(res.Body)  
if err != nil {  
fmt.Println(err)  
return  
}  
var dictResponse DictResponse2  
err = json.Unmarshal(body, &dictResponse)  
if err != nil {  
log.Fatal(err)  
}  
fmt.Println(word, "sougo:", dictResponse.Data.Gaokao.ExamFreqInfo)  
for _, item := range dictResponse.Data.Gaokao.ExamFreqInfo {  
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]  
//var word = "hello"  
query(word)  
query_sougo(word)  
}

三、命令行在线词典(并行版)

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

main函数中使用wg.Add(2)设置等待的Goroutine数量为2,表示需要等待两个Goroutine(即两次请求)完成。

通过mutex.Lock()获取互斥锁,保证对dataMessage变量的安全访问。如果dataMessage为空(即第一个返回的请求),则将响应内容存入其中。最后,通过mutex.Unlock()释放锁,并调用wg.Done()表示该Goroutine已完成。

最后,在主函数中使用wg.Wait()等待所有Goroutine完成,然后打印dataMessage的内容。

package main  
  
import (  
"encoding/json"  
"fmt"  
"io"  
"io/ioutil"  
"log"  
"net/http"  
"strings"  
"sync"  
)  
  
var (  
dataMessage string  
mutex sync.Mutex  
wg sync.WaitGroup  
)  
  
type DictResponse struct {  
//此处省略
}  
  
type DictResponse2 struct {  
//此处省略
}  
  
func query1(word string) {  
  
url := "https://api.interpreter.caiyunai.com/v1/dict"  
method := "POST"  
  
payload := strings.NewReader(`{"trans_type":"en2zh","source":"` + word + `"}`)  
  
client := &http.Client{}  
req, err := http.NewRequest(method, url, payload)  
  
if err != nil {  
fmt.Println(err)  
return  
}  
//此处省略
req.Header.Add() 
  
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)  
}  
  
mutex.Lock()  
if dataMessage == "" {  
dataMessage = word + "\t彩云:\t" + dictResponse.Dictionary.Explanations[0]  
}  
mutex.Unlock()  
  
wg.Done() // 每个Goroutine完成时释放锁和WaitGroup计数  
}  
  
func query_sougo1(word string) {  
  
url := "https://fanyi.sogou.com/api/transpc/text/result"  
method := "POST"  
  
payload := strings.NewReader(`{"from":"auto","to":"zh-CHS","text":"` + word + `","client":"pc","fr":"browser_pc","needQc":1,"s":"dccdc10851a31d187d79396e3467e22e","uuid":"a22e67a0-61f5-4844-a668-1cf0f401fdee","exchange":false}`)  
  
client := &http.Client{}  
req, err := http.NewRequest(method, url, payload)  
  
if err != nil {  
fmt.Println(err)  
return  
}  
//此处省略
req.Header.Add()
  
res, err := client.Do(req)  
if err != nil {  
fmt.Println(err)  
return  
}  
defer res.Body.Close()  
  
body, err := ioutil.ReadAll(res.Body)  
if err != nil {  
fmt.Println(err)  
return  
}  
var dictResponse DictResponse2  
err = json.Unmarshal(body, &dictResponse)  
if err != nil {  
log.Fatal(err)  
}  
  
mutex.Lock()  
if dataMessage == "" {  
dataMessage = word + "搜狗:" + dictResponse.Data.Gaokao.ExamFreqInfo[0].Chinese  
}  
mutex.Unlock()  
  
wg.Done() // 每个Goroutine完成时释放锁和WaitGroup计数  
  
}  
  
func main() {  
wg.Add(2) // 设置等待的Goroutine数量为2  
var word = "hello"  
go query1(word)  
go query_sougo1(word)  
  
wg.Wait() // 等待所有Goroutine完成  
fmt.Println(dataMessage)  
}