Go 语言基础 - 基础语法 | 青训营笔记

107 阅读2分钟

这是我参与「第五届青训营」伴学笔记创作活动的第 1 天

今日内容

学习完了青训营课程 后端入门 - Go 语言原理与实践 中的 走进 Go 语言基础语言Go 语言的实战案例 之后,尝试完成这两节课的课后作业。

作业内容:

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

作业 1

fmt.Scanf 的使用方法为

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

fmt package - fmt - Go Packages

官方描述:

Scanf 扫描从标准输入读取的文本,将连续的空格分隔值存储到由格式确定的连续参数中。 它返回成功扫描的项目数。 如果它小于参数的数量,err 将报告原因。 输入中的换行符必须与格式中的换行符匹配。 一个例外:动词 %c 总是扫描输入中的下一个符文,即使它是空格(或制表符等)或换行符。

简单的使用方法为:

package main

import "fmt"

func main() {
   var a int
   fmt.Printf("input: ")
   _, err := fmt.Scanf("%d", &a)
   if err != nil {
      fmt.Printf("error occurred: %s\n", err.Error())
      return
   }
   fmt.Printf("a is %d\n", a)
}

两个测试样例结果如下

image.png

接下来可以对这个函数封装一下以便让代码更加清晰明了

func input(format string, a ...interface{}) {
   for {
      _, err := fmt.Scanf(format, a...)
      if err != nil {
         fmt.Printf("error occurred: %s\n", err.Error())
         continue
      }
      break
   }
}

最终代码如下:

package main

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

func input(format string, a ...interface{}) {
   for {
      _, err := fmt.Scanf(format, a...)
      if err != nil {
         fmt.Printf("error occurred: %s\n", err.Error())
         continue
      }
      break
   }
}

func main() {
   maxNum := 100
   rand.Seed(time.Now().UnixNano())
   secretNumber := rand.Intn(maxNum)
   // fmt.Println("The secret number is ", secretNumber)

   fmt.Printf("Please input your guess: ")
   for {
      var guess int
      input("%d", &guess)
      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
      }
   }
}

最终结果如下:

image.png

作业 2

我尝试了一会儿,发现基本上的翻译 api 都是需要 token 的,彩云这个好像是因为 token 不会过期所以代码一直能跑,去各大公司注册拿 api 比较麻烦,就暂时不做了。基本操作都和老师上课说的差不多,如果去各大公司注册应该也会有相应的教程。

作业 3

并行请求,其实就是每个请求都作为一个 goroutine 去执行,主要代码如下

func main() {
   var word1, word2 string
   fmt.Printf("input two words: ")
   input("%s %s", &word1, &word2)
   go query(word1)
   go query(word2)
}

其实问题很明显,主线程在协程结束之前就结束了,需要有等待操作,如果担心在输出时会发生打印错乱的情况,可以在打印的时候加锁。

var wg = sync.WaitGroup{}

func query() {
    defer wg.Done()
    ...
}

func main() {
   var word1, word2 string
   fmt.Printf("input two words: ")
   input("%s %s", &word1, &word2)
   wg.Add(2)
   go query(word1)
   go query(word2)
   wg.Wait()
}