Golang基础:实战小项目(猜数游戏and在线词典) | 青训营笔记

193 阅读4分钟

这是我参与「第三届青训营-后端场」笔记创作活动的第1篇笔记。

Golang基础实战小项目

猜数字游戏

首先我们需要生成随机数:

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

这里用到了math/rand包里的Intn函数,maxNum参数会随机生成0-maxNum的一个数字

image.png 这里我们可以发现,虽然已经生成了随机数,但是当我们重复执行3次程序后,每次执行的结果总是相同,如果想要每次生成的数字都不相同,需要我们设置一个随机数种子,一般做法是使用一个时间戳来初始化随机数种子:

maxNum := 100
//使用当前时间的时间戳来初始化随机数种子
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)

image.png 可以看到每次生成的随机数已经不相同了 接着我们就可以读取用户的输入了:

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)
   return
}
//去除换行符
input = strings.TrimSuffix(input, "\n")
//转化为数字
guess, err := strconv.Atoi(input)
if err != nil {
   fmt.Println("Invalid input. Please enter an integer value")
   return
}
fmt.Println("You guess is", guess)

但是这段代码在windows10运行的时候会出现这种错误

image.png 出现这个问题的原因是因为win10平台在你按回车之后,会在参数的末尾加上\r\n作为换行符,而你的代码只处理了\n的这种情况,没有考虑\r\n这种情况。
解决方法如下:

input = strings.TrimSuffix(input, "\r\n")

只需再添加一个'\r'即可

最后只需循环判断数字是否正确即可: 完整代码:

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.TrimSuffix(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
     }
  }
}

运行效果: image.png

在线词典

命令行在线词典原理就是,通过Golang发起请求,调用现成的翻译平台的接口来获取单词数据,这里分别采用百度翻译的接口和有道翻译的接口:

百度翻译

首先是百度翻译,这里我是直接调用百度官方文档的接口,

req, err := http.NewRequest("POST", "https://fanyi-api.baidu.com/api/trans/vip/translate", data)

想要使用这个接口需要自行先注册一个开发者账号,获取appid和secret

image.png 根据上表把参数拼接在data里面,example:

q=apple&from=en&to=zh&appid=2015063000000001&salt=1435660288&sign=f89f9594663708c1605f3d736d01d2d4

也可以发起GET请求,只需把参数拼接在url即可。另外,请求最好设置请求头,以免请求失败,发起请求成功后会获得一个响应,响应的json格式如下:

{
    "from": "en",
    "to": "zh",
    "trans_result": [
        {
            "src": "apple",
            "dst": "苹果"
        }
    ]
}

在golang里我们可以定义一个结构体来接收这个返回响应:

type BaiduResponse struct {
   From        string `json:"from"`
   To          string `json:"to"`
   TransResult []struct {
      Src string `json:"src"`
      Dst string `json:"dst"`
   } `json:"trans_result"`
}

获得响应,再获取我们想要的数据

//获得返回的响应,类型为*http.Response
resp, err := client.Do(req)
if err != nil {
   log.Fatal(err)
}
defer resp.Body.Close()
//读取进bodyText,类型为[]byte
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
   log.Fatal(err)
}
var baiduResponse BaiduResponse
//json序列化
err = json.Unmarshal(bodyText, &baiduResponse)
if err != nil {
   //打印错误日志
   log.Fatal(err)
}
fmt.Println("百度翻译结果:", baiduResponse.TransResult[0].Dst)

执行效果:

image.png

有道翻译

接着再来尝试一下有道翻译,这次是直接通过分析网站上发起的请求来获取我们想要的数据,可通过这种方法直接复制请求

image.png 通过快速生成代码网站来生成golang代码:(Convert curl commands to code (curlconverter.com)) image.png 但是当我们多次请求时会发现,每一次请求的参数sign,salt和lts都是不一样的 image.png 根据查找资料可知,这里的salt是一个时间戳,lts是在salt的基础上加上10以内的随机生成数,而sign则是通过拼接几个参数生成的md5密文,具体生成如下:

//生成时间戳
salt := strconv.FormatInt(time.Now().Unix(), 10)
//加上一个10以内的随机数
lts := salt + strconv.Itoa(rand.Intn(10))
//word为要翻译的单词
code := md5.Sum([]byte("fanyideskweb" + word + salt + "Y2FYu%TNSbMCxc3t2u^XT"))
sign := fmt.Sprintf("%x", code)

最后将数据拼接成请求表单即可,即可查询任意单词

image.png

请求之后会获得一个响应,这里同样可以使用快速生成代码网站来生成golang结构体 ,先复制响应

image.png 通过此网站快速生成golang结构体代码:JSON转Golang Struct - 在线工具 - OKTools

image.png 最后进行类似于百度翻译来操作返回的response即可获得我们想要的参数 运行效果:

image.png