这篇文章主要是对go语言实践课的课后作业的详解
1.猜谜游戏
猜数字游戏也是学习编程语言的一个经典项目,透过这个小程序,我们可以掌握go语言中的输入输出、条件语句以及随机数生成的应用。
生成随机数:
在Go语言中,通过使用标准库中的math/rand包,我们可以实现随机数的生成。
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 设置随机种子,以确保每次运行生成不同的随机数序列
rand.Seed(time.Now().UnixNano())
// 生成一个 [0, n) 的随机整数
n := 10
randomNumber := rand.Intn(n)
fmt.Printf("随机生成的数字: %d\n", randomNumber)
}
请注意,为了确保每次运行都能生成不同的随机数序列,我们使用了time.Now().UnixNano()作为种子来初始化随机数生成器。这有助于保证每次运行程序时都会得到不同的随机数。
程序中随机数的代码
maxnum := 100
rand.Seed(time.Now().UnixNano())
randownum := rand.Intn(maxnum)
fmt.Println(randownum)
通常,用时间戳来作为随机数的种子。(这一点特性和C语言的rand()是类似的。)
接着是让用户自行输入
fmt.Println("请输入你的数字")
reader := bufio.NewReader(os.Stdin)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("输入有误")
return
}
input = strings.TrimSuffix(input, "\r\n"
reader := bufio.NewReader(os.Stdin):这一行代码在Go语言中创建了一个新的bufio.Reader对象,它会从标准输入(os.Stdin)中读取数据。bufio.Reader用于从指定的输入源中进行读取操作,这里我们使用它来从控制台读取用户的输入。
input, err := reader.ReadString('\n'):这行代码从标准输入中读取数据,直到遇到换行符 '\n' 为止。它将读取的数据存储在input变量中,并在读取过程中检查是否发生了错误。如果在读取数据时出现了错误,比如输入流结束或无法读取数据,错误信息将被存储在err变量中。
strings.TrimSuffix() 函数:这一行代码使用strings.TrimSuffix()函数来移除input变量中可能存在的结尾换行符 '\n'。通常情况下,用户的输入以换行符结尾,使用这个函数可以将换行符去除,从而得到更规范的输入。
guess, err := strconv.Atoi(input):这一行代码尝试将经过修剪的input字符串转换为整数类型。它使用strconv.Atoi()函数来进行转换。如果转换成功,转换后的结果会存储在guess变量中;如果转换失败,错误信息将存储在err变量中。这里假设用户的输入是一个表示整数的字符串。如果用户输入的不是合法的整数字符串,转换将会失败并产生错误。
最后加上循环和判断语句即可
for {
guess, err := strconv.Atoi(input)
if err != nil {
fmt.Println("test")
fmt.Println("再试一次")
return
}
fmt.Printf("%T%d", guess, guess)
if count > 5 {
fmt.Println("次数已超过")
return
} else if guess == randownum {
fmt.Println("恭喜你通过了")
return
} else if guess < randownum {
fmt.Println("你输入的太小了")
} else {
fmt.Println("你输入的太大了")
}
count++
}
二、在线词典
第二个案例是一个命令行词典。效果是输入一个单词,命令行中会显示这个单词的发音和注释。
课上主要是对彩云小译网页版进行抓包分析,,使用go发送http请求编写一个翻译小工具。
主要实现:
- 翻译
- 单词字典查询
一、抓包
打开网页按F12调出开发人员工具,再切换到网络选项卡,在输入框里输入内容开始抓包,会抓到个接口,dict为查询字典的接口。
然后分析这个请求
发现能够直接英译中
二、自动编写代码
下面用其他简单的方法去直接编译json代码,先吧url复制下来,待会有用
点击 Copy as cURL(bash) 后,打开这个网址:curlconverter.com/go/
把刚才复制的东西粘贴进去,自动会生成相应的请求代码:
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
var data = strings.NewReader(`{"trans_type":"en2zh","source":"hello"}`)
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,ar;q=0.8")
req.Header.Set("app-name", "xy")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "990faa53baf70befe77f49b01b2daad7")
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", `"Chromium";v="116", "Not)A;Brand";v="24", "Google Chrome";v="116"`)
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/116.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
req.Header.Set("x-forwarded-for", "1.1.1.1")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
复制去vscode中直接运行代码
说明请求成功
接下来需要构造一个结构体,让这个结构体的字段名称和JSON的结构一一对应
三、解析 response body
完成了请求的序列化后,我们还要进行相应的反序列化,这样才能得到结果.
打开这个工具网站:oktools.net/json2go
然后,把彩云小译界面的 response 的json粘贴进去:
可以通过嵌套把结构体整合出来然后替换到原来的代码中去
最后把代码整理一下最终代码如下
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string `json:"user_id"`
}
type DictResponse struct {
Rc int `json:"rc"`
Wiki struct {
} `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 main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD example: simpleDict hello`)
os.Exit(1)
}
word := os.Args[1]
late(word)
}
func late(word string) {
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: word}
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)
}
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")
req.Header.Set("app-name", "xy")
req.Header.Set("cache-control", "no-cache")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "b72e9f6cbb97432941b8adf317a17dee")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("pragma", "no-cache")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Not/A)Brand";v="99", "Google Chrome";v="115", "Chromium";v="115"`)
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/115.0.0.0 Safari/537.36")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
resp, err := client.Do(req)
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
bodyText, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
if resp.StatusCode != 200 {
log.Fatal("bad StatusCode:", resp.StatusCode, "body:", string(bodyText))
}
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
//fmt.Println("%#v\n", dictResponse)
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En,
"US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item)
}
}
在命令行运行:输入要翻译的单词,可以调用接口实现在线翻译