后端go语言实例学习| 青训营笔记

75 阅读5分钟

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

今天笔记总结的是过去几天学习的实例。

猜字游戏

游戏规则:系统随机出一个数字,用户每次猜一个数字,系统能够返回用户猜的数字与系统数字的大小关系,直到用户猜出数字为止,游戏结束。

首先我们需要了解go语言中关于随机数的库函数的调用方式。
使用 `rand.Intn(n)` 可以生成一个 [0,n) 的随机整数。
使用 `rand.Seed(seed)` 可以设置随机种子,seed 为 `int64` 类型。
使用 `rand.Float64()` 可以生成一个 [0.0,1.0) 的随机浮点数。
`time.Now().UnixNano()`是获取当前时间的 Unix 时间戳(以纳秒为单位)。因为时间戳是不断变化的,所以使用当前时间戳作为随机种子能够保证生成的随机数序列是不同的

接下来让我们来试验一下吧。

package main

import (
   "fmt"
   "math/rand"
)

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

我们很快发现如果不加时间戳的随机函数只会进行伪随机。 因此根据我们上述学的知识,进行一次完整的代码:

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("The secret number is smaller than your guess")
      } else if guess < secretNumber {
         fmt.Println("The secret number is bigger than your guess")
      } else {
         fmt.Println("You guessed it!")
         break
      }
   }
}

在线字典

实例要求:输入单词能够正常查询出中文和音标等。 在开始写实例之前,首先我们需要学会抓包: 在课程中我们用的是彩云翻译:

image.png 复制请求方式为post的dict中的curl。 因此我们获得如下json文件:

  -H 'authority: api.interpreter.caiyunai.com' \
  -H 'accept: application/json, text/plain, */*' \
  -H 'accept-language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6' \
  -H 'app-name: xy' \
  -H 'content-type: application/json;charset=UTF-8' \
  -H 'device-id;' \
  -H 'origin: https://fanyi.caiyunapp.com' \
  -H 'os-type: web' \
  -H 'os-version;' \
  -H 'referer: https://fanyi.caiyunapp.com/' \
  -H 'sec-ch-ua: "Not_A Brand";v="99", "Microsoft Edge";v="109", "Chromium";v="109"' \
  -H 'sec-ch-ua-mobile: ?0' \
  -H 'sec-ch-ua-platform: "Windows"' \
  -H 'sec-fetch-dest: empty' \
  -H 'sec-fetch-mode: cors' \
  -H 'sec-fetch-site: cross-site' \
  -H 'user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/109.0.0.0 Safari/537.36 Edg/109.0.1518.55' \
  -H 'x-authorization: token:qgemv4jr1y38jyq6vhvi' \
  --data-raw '{"trans_type":"en2zh","source":"g"}' \
  --compressed

以前的学生课设json文件转化为某种语言的文件本人都是自己手搓的,在这里感谢字节跳动的老师们提供的优质网课。让我再一次感受到了科技发展对于程序员也是一种便利。 json文件在线转换网站 在此我们就获得了相关的go语言代码:

package main

import (
   "fmt"
   "io/ioutil"
   "log"
   "net/http"
   "strings"
)

func main() {
   client := &http.Client{}
   var data = strings.NewReader(`{"trans_type":"en2zh","source":"g"}`)
   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,en;q=0.8,en-GB;q=0.7,en-US;q=0.6")
   req.Header.Set("app-name", "xy")
   req.Header.Set("content-type", "application/json;charset=UTF-8")
   req.Header.Set("device-id", "")
   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", "Microsoft Edge";v="109", "Chromium";v="109"`)
   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/109.0.0.0 Safari/537.36 Edg/109.0.1518.55")
   req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
   resp, err := client.Do(req)
   if err != nil {
      log.Fatal(err)
   }
   defer resp.Body.Close()
   bodyText, err := ioutil.ReadAll(resp.Body)
   if err != nil {
      log.Fatal(err)
   }
   fmt.Printf("%s\n", bodyText)
}

我们还需将整理好的json进行嵌套操作: 在线工具 - OKTools

type AutoGenerated struct {
    Rc int `json:"rc"`
    Wiki struct {
        KnownInLaguages int `json:"known_in_laguages"`
        Description struct {
            Source string `json:"source"`
            Target interface{} `json:"target"`
        } `json:"description"`
        ID string `json:"id"`
        Item struct {
            Source string `json:"source"`
            Target string `json:"target"`
        } `json:"item"`
        ImageURL string `json:"image_url"`
        IsSubject string `json:"is_subject"`
        Sitelink string `json:"sitelink"`
    } `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"`
}

经过上述操作我们就获得了完整代码:

//完整代码
package main
​
import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
    "os"
)
​
type DictRequest struct {
    TransType string `json:"trans_type"`
    Source    string `json:"source"`
    UserID    string `json:"user_id"`
}
​
// DictResponse
type AutoGenerated struct {
    Rc   int `json:"rc"`
    Wiki struct {
        KnownInLaguages int `json:"known_in_laguages"`
        Description     struct {
            Source string      `json:"source"`
            Target interface{} `json:"target"`
        } `json:"description"`
        ID   string `json:"id"`
        Item struct {
            Source string `json:"source"`
            Target string `json:"target"`
        } `json:"item"`
        ImageURL  string `json:"image_url"`
        IsSubject string `json:"is_subject"`
        Sitelink  string `json:"sitelink"`
    } `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(good string) {
    client := &http.Client{}
    request := DictRequest{TransType: "en2zh", Source: "good"}
    buf, err := json.Marshal(request)
    if err != nil {
        log.Fatal(err)
    }
    //创建一个新的io.Reader类型的变量data, 并将buf这个字节数组作为参数传入bytes.NewReader()函数, 以此来创建一个新的io.Reader对象。这个io.Reader对象可以读取buf中的数据,并将读取到的数据赋值给data
    var data = bytes.NewReader(buf) //现在返回的是byte数组而不是字符串
    req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
    if err != nil {
        log.Fatal(err)
    }
    req.Header.Set("Connection", "keep-alive")
    req.Header.Set("DNT", "1")
    req.Header.Set("os-version", "")
    req.Header.Set("sec-ch-ua-mobile", "?0")
    req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36")
    req.Header.Set("app-name", "xy")
    req.Header.Set("Content-Type", "application/json;charset=UTF-8")
    req.Header.Set("Accept", "application/json, text/plain, */*")
    req.Header.Set("device-id", "")
    req.Header.Set("os-type", "web")
    req.Header.Set("X-Authorization", "token:qgemv4jr1y38jyq6vhvi")
    req.Header.Set("Origin", "https://fanyi.caiyunapp.com")
    req.Header.Set("Sec-Fetch-Site", "cross-site")
    req.Header.Set("Sec-Fetch-Mode", "cors")
    req.Header.Set("Sec-Fetch-Dest", "empty")
    req.Header.Set("Referer", "https://fanyi.caiyunapp.com/")
    req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
    req.Header.Set("Cookie", "_ym_uid=16456948721020430059; _ym_d=1645694872")
    resp, err := client.Do(req)
    if err != nil {
        log.Fatal(err)
    }
    //作用:当前函数执行结束时,自动关闭resp.Body这个io.ReadCloser接口类型的对象
    defer resp.Body.Close() //调用resp.Body.Close()函数的执行延迟到当前函数执行结束后
    //ReadAll函数返回两个值,一个是读取的字节数组,赋值给bodyText,另一个是error类型的错误值
    bodyText, err := ioutil.ReadAll(resp.Body) //读取数据
    if err != nil {
        log.Fatal(err)
    }
    if resp.StatusCode != 200 { //判断接口的状态码是否为200
        log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
    }
    var dictResponse AutoGenerated
    err = json.Unmarshal(bodyText, &dictResponse)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(good, "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)
    }
    good := os.Args[1]
    query(good)
}