这是我参与【第五届青训营】笔记创作的第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. 总结
- 从输入的命令中获取到要查询的单词,因为输入的命令是一个字符串数组,长度必须为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)
}
- 开启客户端连接,写好请求体的数据流,传入到请求中
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)
}
- 发送请求,获取到响应,将响应流反序列化为我们定义的响应结构体类型,则我们就可以使用结构体获取到想要的信息了
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)
}