go基础入门和三个简单案例 | 青训营笔记

100 阅读4分钟

这是我参与【第五届青训营】笔记创作的第1天,今天记录下三个go的入门案例

一、猜谜游戏

1. 初始情况

我们想要获取到一个随机数就要使用到math/rand包,还要用到time包去获取时间戳,因为rand方法需要一个随机数种子,则我们可以传入当前程序启动时候的时间,则每次的数字都会变化

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

2. 与用户交互

这里我们需要添加用户的输入功能,实现与用户的交互,我们使用的包有:

1.负责获取流数据的bufio包

2.获取输入输出操作的os包

3.进行字符串操作的strings包

4.进行字符串转换的strconv包

执行流程如下:

1.先从os操作中获取到用户输入的信息,通过bufio转换为流数据

2.在流数据中读取一行数据

3.为了接下来的字符串转换为数字,我们需要对字符串进行处理

4.因为当我们输入回车时,字符串的结尾会有\r\n,则我们需要删除

(这里要注意,不能只操作\n)

5.转化为数字后,我们就可以输出给用户了

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("请输入你的数字")
    reader := bufio.NewReader(os.Stdin)
    input, err := reader.ReadString('\n')
    if err != nil {
        fmt.Println("错误的输入,请重试")
        return
    }
    input = strings.TrimSuffix(input, "\r\n")
    
    guess, err := strconv.Atoi(input)

    if err != nil {
        fmt.Println("输入了错误的数字,请重试")
        return
    }
    fmt.Println("你输入的数字是: ", guess)
}

3. 逻辑判断比较大小

使用一个循环,对于用户的每一次猜测,我们进行逻辑判断,然后告诉用户结果

func check(check int) {
    for i := 1; i < 4; i++ {
        num := get()
        if num > check {
            fmt.Println("你输入的数字太大了,请重新输入")
        } else if num < check {
            fmt.Println("你输入的数字太小了,请重新输入")
        } else {
            fmt.Println("你猜对了")
            return
        }
        fmt.Printf("你还有: %v次机会\n", 3-i)
    }
    fmt.Println("你没有机会了,游戏结束")
}

二、在线词典

1. 在线词典抓包

当我们点击翻译时,会发出一个post请求

这里的json包含两个信息,一个是source就是我们要翻译的单词,

下面是类型

这里是响应:

可以看见我们客户端会得到从服务器端处理来的结果

2. 模拟请求进行本地代码访问

我们先创建一个http的客户端连接client

设置请求的json,和请求的资源

然后我们使用client.Do方法发送我们的请求req

接受到响应后,使用ioutil工具进行读取

defer定义的字段是整个main方法执行完后最后要执行的语句,也就是要关闭客户端连接

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

func main() {
    client := &http.Client{}
    var data = strings.NewReader(`{"source":"good","trans_type":"auto2zh","request_id":"web_fanyi","media":"text","os_type":"web","dict":true,"cached":true,"replaced":true,"detect":true,"browser_id":"879ed359c523c33278ffa20c485bce6b"}`)
    req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/translator", data)
    if err != nil {
        log.Fatal(err)
    }
    // 省略各种请求头设置
    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)
}

3. 实现用户交互

我们上面模拟的是固定的请求,那么接下来我们加入用户操作

因为请求体是json格式,我们要用到encoding/json包

import (
    "bytes"
    "encoding/json"
    "fmt"
    "io/ioutil"
    "log"
    "net/http"
)
// 定义请求体的结构体
type Request struct {
    TransType string `json:"trans_type"`
    Source    string `json:"source"`
}

func main() {
    client := &http.Client{}
    // var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)
    // 创建结构体
    request := Request{TransType: "en2zh", Source: "good"}
    // 通过json转换为字节数组
    buf, err := json.Marshal(request)
    if err != nil {
        log.Fatal(err)
    }
    // 字节数组转换为流数据
    var data = bytes.NewReader(buf)

那么如何处理响应呢,我们还需要声明一个结构体去接收,我们通过oktools工具实现转化

4. 总结

  1. 从输入的命令中获取到要查询的单词,因为输入的命令是一个字符串数组,长度必须为2 : 就像下面一样,前面的是路径,后面的才是单词,则获取数组的最后一个字符串传入查询方法

func main() {
    if len(os.Args) != 2 {
        fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
        `)
        os.Exit(1)
    }
    word := os.Args[1]
    get(word)
}
  1. 开启客户端连接,写好请求体的数据流,传入到请求中
client := &http.Client{}
    request := DictRequest{TransType: "en2zh", Source: work}
    buf, err := json.Marshal(request)
    if err != nil {
        log.Fatal(err)
    }
    var data = bytes.NewReader(buf)
    req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
    if err != nil {
        log.Fatal(err)
    }
  1. 发送请求,获取到响应,将响应流反序列化为我们定义的响应结构体类型,则我们就可以使用结构体获取到想要的信息了
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)
    }
    var dictResponse DictResponse
    err = json.Unmarshal(bodyText, &dictResponse)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(work, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
    for _, item := range dictResponse.Dictionary.Explanations {
        fmt.Println(item)
    }