GO语言工程实践课后作业 | 青训营

67 阅读5分钟

GO语言上手 - 基础语法

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

func main() {  
    maxNumber := 100  
    secretNumber := rand.Intn(maxNumber)  
    for {  
       println("请输入一个数字")  
       var input int  
       _, err := fmt.Scan(&input)  
       if err != nil {  
          println("输入错误,请重新输入")  
          continue  
       }  
  
       if input < secretNumber {  
          println("猜小了")  
       } else if input > secretNumber {  
          println("猜大了")  
       } else {  
          println("猜对了")  
          break  
       }  
    }  
}

在这个示例中,我将猜谜游戏的代码进行了优化,使用了 fmt.Scan 来获取用户输入。首先,设定了一个最大数值作为上限,然后使用 rand.Intn 生成一个随机的答案。接下来,我们进入一个无限循环,不断询问用户输入。通过 fmt.Scan,我们可以更简单地读取用户输入的数字。根据用户的输入,通过逻辑判断告诉用户猜得是大了还是小了,直到用户猜对为止。

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

package main  
  
import (  
    "bytes"  
    "encoding/json"    "fmt"    "io"    "log"    "net/http"    "strings"    "sync")  

func main() {  
    var x string  
    _, err := fmt.Scan(&x)  
    if err != nil {  
       return  
    }  
    baiDu(x)  
}  

type BaiDuAnswer struct {  
    Zly     string `json:"zly"`  
    Message string `json:"message"`  
    Code    int    `json:"code"`  
    UUID    string `json:"uuid"`  
    Sugg    []struct {  
       K string `json:"k"`  
       V string `json:"v"`  
    } `json:"sugg"`  
    Direction string `json:"direction"`  
}  
  
func baiDu(word string) {  
    client := &http.Client{}  
    var data = strings.NewReader(`from=auto&to=zh-CHS&client=web&text=` + word + `&uuid=1a5bfb0b-cc16-435f-a834-96f768a77192&pid=sogou-dict-vr&addSugg=on`)  
    req, err := http.NewRequest("POST", "https://fanyi.sogou.com/reventondc/suggV3", data)  
    if err != nil {  
       log.Fatal(err)  
    }  
    req.Header.Set("Accept", "application/json")  
    req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7")  
    req.Header.Set("Connection", "keep-alive")  
    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")  
    req.Header.Set("Cookie", "ABTEST=0|1680689048|v17; SUID=E2D5BE3DD352A00A00000000642D4798; SMYUV=1687178571725983; ssuid=4854869298; SNUID=DE6EEAE0909691C0C562F6E790A3BF92; wuid=1690294410878; FQV=a6937b8d34b3fe4cf9513bdc6ee41281; translate.sess=2e73b43c-aaaf-4043-b9b5-13dbfef40868; SUV=1690294410822; SGINPUT_UPSCREEN=1690294410841")  
    req.Header.Set("Origin", "https://fanyi.sogou.com")  
    req.Header.Set("Referer", "https://fanyi.sogou.com/text")  
    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/114.0.0.0 Safari/537.36 Edg/114.0.1823.67")  
    req.Header.Set("sec-ch-ua", `"Not.A/Brand";v="8", "Chromium";v="114", "Microsoft Edge";v="114"`)  
    req.Header.Set("sec-ch-ua-mobile", "?0")  
    req.Header.Set("sec-ch-ua-platform", `"Windows"`)  
  
    resp, err := client.Do(req)  
    defer func(Body io.ReadCloser) {  
       err := Body.Close()  
       if err != nil {  
  
       }    }(resp.Body)  
    bodyText, err := io.ReadAll(resp.Body)  
    if err != nil {  
       log.Fatal(err)  
    }  
    //fmt.Printf(string(bodyText))  
    var answer BaiDuAnswer  
    err = json.Unmarshal(bodyText, &answer)  
    if err != nil {  
       log.Fatal(err)  
    }  
    for _, item := range answer.Sugg {  
       println(item.K, ":", item.V)  
    }  
}

在这个例子中,展示了如何使用 Go 语言构建一个命令行词典工具,并增加了对另一种翻译引擎的支持。通过 http.Client 构建了一个 HTTP 请求,模拟了请求头信息,并发送 POST 请求到搜狗翻译的接口。通过解析 JSON 响应,我们可以得到翻译结果,然后将结果输出给用户。

需要注意的是,实际使用时可能需要注意网站的反爬虫机制,百度似乎会根据请求头信息进行限制,所以在构建请求时需要注意设置合适的请求头信息。

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

var vg sync.WaitGroup  
vg.Add(2)  

go func() {  
   defer vg.Done()  
   caiYun(x)  
}()  
go func() {  
   defer vg.Done()  
   baiDu(x)  
}()  
vg.Wait()  

在这个例子中,我在第二个例子的基础上进一步优化了代码,实现了并行请求两个翻译引擎来提高响应速度。使用了 sync.WaitGroup 来等待两个并行任务的完成。通过使用两个 go func 分别请求不同的翻译引擎,可以同时进行两个请求,从而加快翻译的响应速度。需要注意的是,并行输出可能会造成输出混乱,因此在处理输出时需要注意。

总之,这个例子展示了如何利用 Go 语言的并发特性来优化程序性能,提高响应速度。同时,我们也看到了如何构建 HTTP 请求并解析 JSON 响应,从而实现基本的网络请求和数据处理功能。

总结

总的来说,Go 语言作为一门新兴的编程语言,相对于我之前主要使用的 C++,在并发处理方面提供了更为便捷的解决方案。通过 Go 的并发原语和 Goroutine,可以轻松地实现并发任务的同时执行,从而提高程序的性能和响应速度。在使用 Go 进行并发编程时,需要特别注意一些可能导致问题的地方,如资源竞争和并发安全性,因此合理使用锁和其他同步机制是十分重要的。

相较于 C++,Go 在语法和语言特性上也有一些不同之处。虽然有一些不同的函数和概念,但这些差异相对较小,不会给有开发者带来太大的困扰。事实上,很多基本的编程概念在两者之间是通用的,因此对于有其他编程语言背景的开发者来说,掌握 Go 语言并不是一件难事。

除了并发处理和语法特性外,Go 语言还提供了丰富的标准库和第三方库,涵盖了从网络通信到文件处理等各个领域。这为开发者提供了更多的工具和资源,可以更高效地完成各种任务。