随机猜数字游戏
使用go语言实现一个简单的猜数字游戏
实现原理
通过 for 和 随机数生成函数 rand.Intn(maxNum)
随机数生成
package main
import (
"fmt"
"math/rand"
)
func main() {
maxNum := 100
// GO最新标准已经弃用
//rand.Seed(time.Now().UnixNano())
// 不需要设定种子即可生成随机数
// 生成的是 在 [0,maxNum-1] 之间的随机数
secretNum := rand.Intn(maxNum)
fmt.Println(secretNum)
}
/*
* 27
*/
相关官方文档
func Seed(seed int64)
函数 Seed 已弃用rand package - math/rand - Go Packages
func Seed(seed int64) Seed 使用提供的种子值将默认源初始化为确定性状态。当除以 2³¹-1 时具有相同余数的种子值将生成相同的伪随机序列。与 Rand.Seed 方法不同,Seed 可以安全地用于并发使用。
如果未调用 Seed,则生成器将在程序启动时随机设置种子。
在 Go 1.20 之前,生成器在程序启动时类似于 Seed(1) 的方式被设置种子。要强制使用旧的行为,请在程序启动时调用 Seed(1)。或者,在调用此包中的任何函数之前,在环境中设置 GODEBUG=randautoseed=0。
已弃用:从 Go 1.20 开始,没有理由用随机值调用 Seed。调用 Seed 并传入已知值以获取特定结果序列的程序应使用 New(NewSource(seed)) 来获取局部随机生成器。
添加输入
bufio 包
bufio 是一个包,它为 I/O 提供缓冲。
bufio 包提供了一些读取器(Reader)和写入器(Writer)类型,它们在内存中维护一个缓冲区,从而减少对底层 I/O 调用的次数。
常用的类型和函数
类型
Reader: 从一个 io.Reader 对象读取数据,并提供缓冲。Writer: 向一个 io.Writer 对象写入数据,并提供缓冲。ReadWriter: 结合了Reader和Writer,可以同时用于读写。
函数
NewReader(rd io.Reader) *Reader: 创建一个新的Reader,它将从提供的io.Reader读取数据。NewWriter(w io.Writer) *Writer: 创建一个新的Writer,它将向提供的io.Writer写入数据。NewReadWriter(r *Reader, w *Writer) *ReadWriter: 创建一个新的ReadWriter,它将使用提供的Reader和Writer进行读写操作。
读取器(Reader)
Read(p []byte) (n int, err error): 从缓冲区读取数据到p中。ReadByte() (byte, error): 读取并返回一个字节。ReadBytes(delim byte) ([]byte, error): 读取直到遇到分隔符delim,返回读取的数据(包括分隔符)。ReadString(delim byte) (string, error): 类似于ReadBytes,但返回的是字符串,包括分隔符Peek(n int) ([]byte, error): 返回缓冲区中下一个n个字节,而不进行读取。
写入器(Writer)
Write(p []byte) (n int, err error): 将p中的数据写入缓冲区。WriteString(s string) (int, error): 将字符串s写入缓冲区。WriteByte(c byte) error: 写入一个字节。Flush() error: 将缓冲区中的数据写入底层的 io.Writer。
基本用法
package main
import (
"bufio"
"bytes"
"fmt"
"os"
)
func main() {
// 创建一个新的 bytes.Buffer
var buffer bytes.Buffer
// 创建一个新的 Writer 和 Reader
writer := bufio.NewWriter(&buffer)
reader := bufio.NewReader(&buffer)
// 创建一个 ReadWriter
readWriter := bufio.NewReadWriter(reader, writer)
// 写入数据
message := "Hello, B3Q!\n"
n, err := readWriter.WriteString(message)
if err != nil {
fmt.Println("Error writing to buffer:", err)
return
}
fmt.Printf("Wrote %d bytes to buffer by ReadWriter\n", n)
// 刷新缓冲区,确保所有数据都被写入到底层的 io.Writer
if err := readWriter.Flush(); err != nil {
fmt.Println("Error flushing buffer:", err)
return
}
// 使用 ReadWriter 读取之前写入的数据
line, err := readWriter.ReadString('\n')
if err != nil {
fmt.Println("Error reading from ReadWriter:", err)
return
}
fmt.Printf("Read from ReadWriter: %s", line)
}
添加输入的随机数生成
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
)
func main() {
maxNum := 114514 // 设置猜测数字的最大范围
secretNumber := rand.Intn(maxNum) // 生成一个0到maxNum-1之间的随机数作为秘密数字
fmt.Println("The secret number is ", secretNumber)
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.Trim(input, "\r\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) // 打印用户猜测的数字
}
添加for循环和提示
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
)
func main() {
maxNum := 114514 // 设置猜测数字的最大范围
secretNumber := rand.Intn(maxNum) // 生成一个0到maxNum-1之间的随机数作为秘密数字
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("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 // 退出循环
}
}
}
使用 fmt.Scanf 优化输入
fmt.Scanf
fmt 包提供了一个函数 Scanf,它是用于根据格式字符串从标准输入(通常是键盘输入)读取数据到指定的变量中
func Scanf(format string, a ...interface{}) (n int, err error)
format: 一个格式字符串,它指定如何解释输入。格式字符串中的每个格式化动词都会对应一个参数,用于存储读取的值。例如,%d表示读取一个整数,%s表示读取一个字符串等。a ...interface{}: 这是一个可变数量的参数,每个参数都必须是一个指向变量的指针。这些变量用于存储Scanf读取的值。n: 返回成功读取并赋值的输入项数。err: 返回在读取过程中遇到的任何错误。
示例
package main
import "fmt"
func main() {
var name string
var age int
// 提示用户输入姓名和年龄
fmt.Print("Enter your name and age: ")
// 使用Scanf读取用户输入的姓名和年龄
// 类似于c语言输入
// 其中 %s 输入一个字符串 %d 输入一个数字 它们是格式化动词
_, err := fmt.Scanf("%s %d", &name, &age)
if err != nil {
fmt.Println("Error reading input:", err)
return
}
// 打印读取到的值
fmt.Printf("Hello, %s. You are %d years old.\n", name, age)
}
/*
* Enter your name and age: b3q 114514
* Hello, b3q. You are 114514 years old.
*/
其它格式化动词
布尔值
- %t: 输出布尔值(true 或 false)
整数
- %d: 输出十进制整数。
- %b: 输出二进制整数。
- %c: 输出对应的 Unicode 码点字符。
- %o: 输出八进制整数。
- %x: 输出十六进制整数,使用小写字母。
- %X: 输出十六进制整数,使用大写字母。
- %U: 输出 Unicode 格式字符(例如 “U+1234”)
浮点数和复数
- %f: 输出十进制形式的小数或浮点数。
- %e 或 %E: 输出科学记数法形式(例如 1.234e+02)
- %g 或 %G: 根据情况选择 %e、%E 或 %f,以更紧凑的方式输出
字符串和字节切片
- %s: 输出字符串或切片的字符串表示形式。
- %q: 输出带双引号的字符串或切片的字符串表示形式。
- %x: 输出十六进制编码的字符串,每个字节用两个十六进制数字表示。
- %X: 类似 %x,但使用大写字母
指针
- %p: 输出十六进制表示的指针地址
使用 fmt.Scanf 优化的程序
package main
import (
"fmt"
"math/rand"
)
func main() {
maxNum := 10
secretNumber := rand.Intn(maxNum)
var guess int
fmt.Println("Please input your guess")
// 无限循环,直到用户猜对数字
for {
_, err := fmt.Scanf("%d", &guess) // 使用Scanf读取用户输入的整数
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 // 退出循环
}
}
}
简单字典(查单词)
使用go语言通过发送请求实现一个简单查单词功能(简单爬虫)
PS:需要了解HTTP 协议基础内容:请求与响应
实现原理
通过go语言爬取 ajax 请求
爬取网站:彩云翻译
寻找 ajax
首先按 f12 打开控制台,选择网络,点击 XHR
这里使用的是 edge 浏览器
输入待查询的单词,这里输入的是 tom
可以发现右边控制台出现了名为dict的ajax请求
点击 dict,选择预览
出现了输入单词的中文译文 explanation (Unicode编码格式,因为译文是中文) ,音标 prons。表明这个ajax是要爬取的
点击响应
可以发现是一个json格式的字符串,接下来就是进行构造请求,获取响应
构造请求
点击标头,可以发现请求的url(链接)是 api.interpreter.caiyunai.com/v1/dict,请求方式是 post,说明客户端(通常是用户的网页浏览器或者是一个应用程序,这里是网页浏览器)需要向服务器发送数据,以获取资源,而get请求则不需要。
点击负载,查看负载的数据
可以发现是一个json格式的字符串,说明当向这个url发送post请求时,需要带上上图格式的json格式的字符串,其中
source 表示翻译的文字内容,这是要翻译的是 tom 这个单词
tans_type 表示 从什么语言翻译成另一种语言,这里 en2zh 说明从英文(en)翻译成中文(zh) ,其中的 2 表示 '到' 的意思
接下来进行构造请求
首先点击标头,点击展开 请求标头
这是要构造的请求的请求头,可以发现请求的方法,请求的协议,请求需要token等内容
需要根据这个请求头进行构造,右键 dict,选择复制为url(bash)
然后将复制的内容复制到 Convert curl commands to Go (curlconverter.com) ,选择 go
可以快速生成 go语言类型的请求,这里添加了注释
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
// 创建一个 HTTP 客户端
client := &http.Client{}
// 准备请求数据,以 JSON 格式字符串的形式
var data = strings.NewReader(`{"trans_type":"en2zh","source":"tom"}`)
// 创建一个新的 HTTP POST 请求
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
// 如果创建请求时发生错误,记录错误并退出程序
log.Fatal(err)
}
// 设置请求头
req.Header.Set("accept", "application/json, text/plain, */*") // 设置接受的内容类型
req.Header.Set("accept-language", "zh") // 设置接受的语言
req.Header.Set("app-name", "xiaoyi") // 设置应用名称
req.Header.Set("authorization", "Bearer") // 设置授权类型
req.Header.Set("content-type", "application/json;charset=UTF-8") // 设置内容类型为 JSON
req.Header.Set("device-id", "b7feaa2827a466315abeb73e554ba173") // 设置设备 ID
req.Header.Set("origin", "https://fanyi.caiyunapp.com") // 设置请求来源
req.Header.Set("os-type", "web") // 设置操作系统类型
req.Header.Set("os-version", "") // 设置操作系统版本(这里为空)
req.Header.Set("priority", "u=1, i") // 设置请求优先级
req.Header.Set("referer", "https://fanyi.caiyunapp.com/") // 设置引用页(Referer)
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Microsoft Edge";v="128"`) // 设置浏览器用户代理字符串
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/128.0.0.0 Safari/537.36 Edg/128.0.0.0") // 设置用户代理字符串
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") // 设置自定义授权令牌,token
// 发送请求
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 或 goland 运行代码结果为:
{"rc":0,"wiki":{},"dictionary":{"prons":{"en-us":"[t\u0251m]","en":"[t\u0254m]"},"explanations":["n.\u96c4\u6027\u52a8\u7269,\u96c4\u732b"],"synonym":[],"antonym":[],"wqx_example":[],"entry":"tom","type":"word","related":[],"source":"wenquxing"}}
发现与要爬取的响应一致
并且通过更改 var data = strings.NewReader({"trans_type":"en2zh","source":"tom"}) 中的 source,可以更改要翻译的字符
`var data = strings.NewReader(`{"trans_type":"en2zh","source":"Jerry"}`)` // 更改要查询的文字内容为 Jerry
运行结果
{"rc":0,"wiki":{},"dictionary":{"prons":{"en-us":"[\u02c8d\u0292\u03b5r\u026a]","en":"[\u02c8d\u0292eri]"},"explanations":["n.\u6770\u745e(\u7537\u5b50\u540d)","[\u4fda]\u5fb7\u56fd\u58eb\u5175;\u5fb7\u56fd\u4eba"],"synonym":[],"antonym":[],"wqx_example":[],"entry":"Jerry","type":"word","related":[],"source":"wenquxing"}}
优化代码
观察输入和输出,可以发现请求的负载和响应的内容都是一个json格式的字符串,所以通过构造json结构体简化输入和输出,优化代码
点击dict的响应
复制内容到JSON转Golang Struct - 在线工具 - OKTools (iokde.com),进行生成,选择 转换-嵌套
获取生成结构体
type AutoGenerated 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 []interface{} `json:"synonym"`
Antonym []interface{} `json:"antonym"`
WqxExample []interface{} `json:"wqx_example"`
Entry string `json:"entry"`
Type string `json:"type"`
Related []interface{} `json:"related"`
Source string `json:"source"`
} `json:"dictionary"`
}
同理获取请求负载的结构体
type AutoGenerated struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
}
更改结构体名字
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
}
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 []interface{} `json:"synonym"`
Antonym []interface{} `json:"antonym"`
WqxExample []interface{} `json:"wqx_example"`
Entry string `json:"entry"`
Type string `json:"type"`
Related []interface{} `json:"related"`
Source string `json:"source"`
} `json:"dictionary"`
}
使用上面的结构体,并进行基本封装,将主要查询封装成函数query,输入则在函数main
内
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"os"
)
// DictRequest 定义了发送到彩云翻译的请求结构
type DictRequest struct {
TransType string `json:"trans_type"` // 翻译类型,例如 "en2zh" 表示从英语到中文
Source string `json:"source"` // 要翻译的源文本
}
// DictResponse 定义了从彩云翻译接收的响应结构
type DictResponse struct {
Rc int `json:"rc"` // 响应代码,用于指示请求是否成功
Wiki struct {
} `json:"wiki"` // Wiki字段,可能包含与单词相关的维基百科信息
// Dictionary字段包含了单词的详细解释信息
Dictionary struct {
Prons struct {
EnUs string `json:"en-us"` // 美式发音
En string `json:"en"` // 英式发音
} `json:"prons"`
Explanations []string `json:"explanations"` // 单词解释列表
Synonym []interface{} `json:"synonym"` // 同义词列表
Antonym []interface{} `json:"antonym"` // 反义词列表
WqxExample []interface{} `json:"wqx_example"` // 示例句子列表
Entry string `json:"entry"` // 单词本身
Type string `json:"type"` // 单词类型(如名词、动词等)
Related []interface{} `json:"related"` // 相关词汇列表
Source string `json:"source"` // 解释来源
} `json:"dictionary"`
}
// query函数用于查询指定单词的翻译和解释
func query(word string) {
client := &http.Client{} // 创建HTTP客户端
// 构造请求结构体
request := DictRequest{TransType: "en2zh", Source: word}
buf, err := json.Marshal(request) // 将请求结构体序列化为JSON
if err != nil {
log.Fatal(err) // 如果序列化失败,记录错误并退出
}
// 创建新的HTTP请求
var data = bytes.NewReader(buf) // 将JSON数据转换为io.Reader
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)
if err != nil {
log.Fatal(err) // 如果创建请求失败,记录错误并退出
}
// 设置HTTP请求头
req.Header.Set("accept", "application/json, text/plain, */*")
req.Header.Set("accept-language", "zh")
req.Header.Set("app-name", "xiaoyi")
req.Header.Set("authorization", "Bearer")
req.Header.Set("content-type", "application/json;charset=UTF-8")
req.Header.Set("device-id", "b7feaa2827a466315abeb73e554ba173")
req.Header.Set("origin", "https://fanyi.caiyunapp.com")
req.Header.Set("os-type", "web")
req.Header.Set("os-version", "")
req.Header.Set("priority", "u=1, i")
req.Header.Set("referer", "https://fanyi.caiyunapp.com/")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Microsoft Edge";v="128"`)
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/128.0.0.0 Safari/537.36 Edg/128.0.0.0")
req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi")
// 发送HTTP请求
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) // 如果读取失败,记录错误并退出
}
// 检查HTTP状态码
if resp.StatusCode != 200 {
log.Fatal("bad StatusCode:", resp.StatusCode, "body", string(bodyText))
}
// 将响应体中的JSON数据反序列化到DictResponse结构体中
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err) // 如果反序列化失败,记录错误并退出
}
// 打印单词的发音和解释
fmt.Println(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item) // 打印每个解释
}
}
// main函数是程序的入口点
func main() {
// 检查命令行参数数量是否正确
if len(os.Args) != 2 {
// 如果参数数量不正确,打印使用方法并退出
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1) // 退出程序,返回错误码1
}
word := os.Args[1] // 获取要查询的单词
query(word) // 调用query函数查询单词
}
通过在命令行输入指令运行
PS G:\GoStudy> go run main.go tom
结果
tom UK: [tɔm] US: [tɑm]
n.雄性动物,雄猫
更换翻译网站为:火山翻译
跟上面彩云翻译的步骤大部分一致,但是其中查找相关的ajax请求有点麻烦
因为有许多前缀相同的ajax请求,需要点击响应,根据时间进行查找
然后重复上面步骤,得到go代码,其中更改words可以改变要查的单词
package main
import (
"fmt"
"io"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
// 更改 words 后面的值,可以改变要查询的单词
var data = strings.NewReader(`{"source":"youdao","words":["milk"],"source_language":"en","target_language":"zh"}`)
req, err := http.NewRequest("POST", "https://translate.volcengine.com/web/dict/detail/v1/?msToken=&X-Bogus=DFSzswVLQDVmHKA/tsxyD5TQh4CK&_signature=_02B4Z6wo00001M8G2cwAAIDBEF0qgR0wjaTPBt1AAFTt8XJzCW7GF0cRJMGx5Zz41ixEjtMtGWj3QFqbP5RqADkyxbn9ziMeRoEXSIXCwGaV91dBwiJ78OjBxhehtNuk7oPBYEDaCE-DPx3m32", data)
if err != nil {
log.Fatal(err)
}
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("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Cookie", "i18next=zh-CN; s_v_web_id=verify_m33ucjvy_9nOqXMPH_Fz81_4KlX_AmuB_lzvdSeet2UsA; ttcid=79cdc8e608df48569bde51b3676dee1378; tt_scid=hcd24O6gTJ0On61Xtinp5k7FnU5IwSTQ5xulXThhPTObP-yu-mI-mbXARDbiXhvi15b0")
req.Header.Set("Origin", "https://translate.volcengine.com")
req.Header.Set("Referer", "https://translate.volcengine.com/mobile?category=&home_language=zh&source_language=detect&target_language=zh&text=milk")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Microsoft Edge";v="128"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
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)
}
类似上面彩云翻译,使用结构体优化代码,并进行简单封装
同时,因为响应的 Details 参数过多,所以又编写了另一个结构体ParasResponse来格式化 Details 参数,便于处理
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
"os"
)
type DictRequest struct {
Source string `json:"source"`
Words []string `json:"words"`
SourceLanguage string `json:"source_language"`
TargetLanguage string `json:"target_language"`
}
type DictResponse struct {
Details []struct {
Detail string `json:"detail"`
Extra string `json:"extra"`
} `json:"details"`
BaseResp struct {
StatusCode int `json:"status_code"`
StatusMessage string `json:"status_message"`
} `json:"base_resp"`
}
type ParasResponse struct {
ErrorCode string `json:"errorCode"`
Msg string `json:"msg"`
RequestID string `json:"requestId"`
Result []struct {
Ec struct {
Basic struct {
ExamType []string `json:"examType"`
Explains []struct {
Pos string `json:"pos"`
Trans string `json:"trans"`
} `json:"explains"`
Phonetic string `json:"phonetic"`
UkPhonetic string `json:"ukPhonetic"`
UkSpeech string `json:"ukSpeech"`
UsPhonetic string `json:"usPhonetic"`
UsSpeech string `json:"usSpeech"`
WordFormats []struct {
Name string `json:"name"`
Value string `json:"value"`
} `json:"wordFormats"`
} `json:"basic"`
Dict string `json:"dict"`
Etymology struct {
ZhCHS []struct {
Description string `json:"description"`
Detail string `json:"detail"`
Source string `json:"source"`
} `json:"zh-CHS"`
} `json:"etymology"`
ExplainWithSentences []struct {
Explain string `json:"explain"`
Proportion string `json:"proportion"`
SentenceSampleList []struct {
Sentence string `json:"sentence"`
SentenceBold string `json:"sentenceBold"`
Source string `json:"source"`
Translation string `json:"translation"`
} `json:"sentenceSampleList"`
} `json:"explainWithSentences"`
IsWord bool `json:"isWord"`
Lang string `json:"lang"`
MTerminalDict string `json:"mTerminalDict"`
Phrases []struct {
Meanings []string `json:"meanings"`
Phrase string `json:"phrase"`
} `json:"phrases"`
RelWord struct {
Rels []struct {
Rel struct {
Pos string `json:"pos"`
Words []struct {
Tran string `json:"tran"`
Word string `json:"word"`
} `json:"words"`
} `json:"rel"`
} `json:"rels"`
Stem string `json:"stem"`
Word string `json:"word"`
} `json:"relWord"`
ReturnPhrase []string `json:"returnPhrase"`
SentenceSample []struct {
Sentence string `json:"sentence"`
SentenceBold string `json:"sentenceBold"`
Source string `json:"source"`
Translation string `json:"translation"`
} `json:"sentenceSample"`
Synonyms []struct {
Pos string `json:"pos"`
Trans string `json:"trans"`
Words []string `json:"words"`
} `json:"synonyms"`
Web []struct {
Meanings []string `json:"meanings"`
Phrase string `json:"phrase"`
} `json:"web"`
WebDict string `json:"webDict"`
} `json:"ec"`
} `json:"result"`
UpdatedAt int `json:"updated_at"`
}
func query(word string) {
client := &http.Client{}
request := DictRequest{Source: "youdao", Words: []string{word}, SourceLanguage: "en", TargetLanguage: "zh"}
buf, err := json.Marshal(request)
if err != nil {
log.Fatal(err)
}
var data = bytes.NewReader(buf)
req, err := http.NewRequest("POST", "https://translate.volcengine.com/web/dict/detail/v1/?msToken=&X-Bogus=DFSzswVLQDVmHKA/tsxyD5TQh4CK&_signature=_02B4Z6wo00001M8G2cwAAIDBEF0qgR0wjaTPBt1AAFTt8XJzCW7GF0cRJMGx5Zz41ixEjtMtGWj3QFqbP5RqADkyxbn9ziMeRoEXSIXCwGaV91dBwiJ78OjBxhehtNuk7oPBYEDaCE-DPx3m32", data)
if err != nil {
log.Fatal(err)
}
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("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Cookie", "i18next=zh-CN; s_v_web_id=verify_m33ucjvy_9nOqXMPH_Fz81_4KlX_AmuB_lzvdSeet2UsA; ttcid=79cdc8e608df48569bde51b3676dee1378; tt_scid=hcd24O6gTJ0On61Xtinp5k7FnU5IwSTQ5xulXThhPTObP-yu-mI-mbXARDbiXhvi15b0")
req.Header.Set("Origin", "https://translate.volcengine.com")
req.Header.Set("Referer", "https://translate.volcengine.com/mobile?category=&home_language=zh&source_language=detect&target_language=zh&text=milk")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36 Edg/128.0.0.0")
req.Header.Set("sec-ch-ua", `"Chromium";v="128", "Not;A=Brand";v="24", "Microsoft Edge";v="128"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
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)
}
var parasResponse ParasResponse
err = json.Unmarshal([]byte(dictResponse.Details[0].Detail), ¶sResponse)
if err != nil {
log.Fatal(err)
}
for _, explaination := range parasResponse.Result[0].Ec.Synonyms {
fmt.Println(explaination.Pos, explaination.Trans)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1)
}
word := os.Args[1]
query(word)
}
使用命令行查询单词 good
PS G:\GoStudy> go run main.go good
结果为:
adj. 好的;优良的;愉快的;虔诚的
n. 好处;善行;慷慨的行为
adv. 好