这是我参与「第五届青训营 」伴学笔记创作活动的第 1 天
1.1.猜谜游戏
- 需求:程序首先会生成一个介于 0 到 100 之间的随机整数,然后提示玩家进行猜测。玩家每次输入一个数字,程序会告诉玩家这个猜测的值是高于还是低于那个秘密的随机数,并且让玩家再次猜测。如果猜对了,就告诉玩家胜利并且退出程序。
1.1.1.rand的使用(一)
- 使用rand,但是未指定随机数种子,此时调用 rand.Intn() 每次返回的数字都一样
package main
import (
"fmt"
"math/rand"
)
func main() {
maxNum := 100
secretNumber := rand.Intn(maxNum) // 获取随机数,但是发现每次返回的数字都一样
fmt.Println("The secret number is ", secretNumber)
}
1.1.2.rand的使用(二)
- 使用 rand.Seed() 指定随机数种子,这里使用时间戳作为随机数种子,然后再使用 rand.Intn() 获取随机数,就没问题了
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
// 1.获取一个0-100的随机数
maxNum := 100
rand.Seed(time.Now().UnixNano()) // 指定随机数种子
secretNumber := rand.Intn(maxNum) // 获取随机数
fmt.Println("The secret number is ", secretNumber)
}
1.1.3.读取用户输入,并转成int整数
- 读取用户输入
- 使用标准输入文件,转成reader变量方便操作
- 返回的结果包含结尾的换行符,需要去掉
- 如果发生错误,直接返回
- 使用
strconv.Atoi()将用户输入转成int类型整数
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func main() {
// 1.获取一个0-100的随机数
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is ", secretNumber)
// 2.获取用户输入,即用户猜测的数字,并进行初步的处理
fmt.Println("Please input your guess")
reader := bufio.NewReader(os.Stdin) // 使用标准输入文件,转成reader变量方便操作
input, err := reader.ReadString('\n') // 返回的结果包含结尾的换行符,需要去掉
if err != nil { // 发生错误,直接返回
fmt.Println("An error occured while reading input. Please try again", err)
return
}
input = strings.TrimSuffix(input, "\n") // 去除尾部的\n
// 3.将用户输入转成int类型整数
guess, err := strconv.Atoi(input)
if err != nil { // 发生错误,提示用户输入整数
fmt.Println("Invalid input. Please enter an integer value")
return
}
fmt.Println("You guess is", guess)
}
1.1.4.对用户输入添加判断逻辑
- 判断 用户猜测整数 与 秘密数字 的关系
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)
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occured while reading input. Please try again", err)
return
}
input = strings.TrimSuffix(input, "\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)
// 1.上述逻辑,已经生成秘密数字,并获取用户输入的整数
// 2.判断 用户猜测整数 与 秘密数字 的关系
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!")
}
}
1.1.5.增加循环判断逻辑
- 增加循环判断逻辑
- 如果用户猜错,则重新生成一个数字,重新获取用户输入,然后进行比较
- 直到用户猜对为止
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)
// 1.死循环,直到用户猜对停止
for {
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occured while reading input. Please try again", err)
continue
}
input = strings.TrimSuffix(input, "\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 // 2.用户猜对,才会退出
}
}
}
1.2.在线词典
- 需求:实现一个输入英文,返回中文翻译的程序
1.2.1.获取彩云小译API
- 使用浏览器打开网址:fanyi.caiyunapp.com/#/
- 随便输入一个单词,自动翻译时会发生请求,抓包post请求api,包名称为dict
1.2.2.复制请求的cURL(bash)命令,使用工具生成GO代码
curl 'https://api.interpreter.caiyunai.com/v1/dict' \
-H 'Accept: application/json, text/plain, */*' \
-H 'Accept-Language: zh-CN,zh;q=0.9' \
-H 'Connection: keep-alive' \
-H 'Content-Type: application/json;charset=UTF-8' \
-H 'Origin: https://fanyi.caiyunapp.com' \
-H 'Referer: https://fanyi.caiyunapp.com/' \
-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/101.0.4951.54 Safari/537.36' \
-H 'X-Authorization: token:qgemv4jr1y38jyq6vhvi' \
-H 'app-name: xy' \
-H 'device-id: ' \
-H 'os-type: web' \
-H 'os-version: ' \
-H 'sec-ch-ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"' \
-H 'sec-ch-ua-mobile: ?0' \
-H 'sec-ch-ua-platform: "Windows"' \
--data-raw '{"trans_type":"en2zh","source":"good"}' \
--compressed
- 打开网址:curlconverter.com/#go ,输入上述shell命令,选择转换成Go语言,即可自动生成代码
-
生成代码如下,即为第一版代码。
- 运行代码,可以打印出返回结果
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
func main() {
// 1.创建了一个 HTTP client,创建的时候也可以指定参数
client := &http.Client{}
// 2.构造一个 HTTP 请求
var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`) // 将 请求体字符串 转成 流数据
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data) // 创建请求
if err != nil { // 请求创建失败,则 先打印错误信息,然后直接退出进程
log.Fatal(err) // log.Fatal(),相当于先调用Print(),然后调用os.Exit(1)
}
// 设置请求头的一些信息
req.Header.Set("Accept", "application/json, text/plain, */*")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/json;charset=UTF-8")
req.Header.Set("Origin", "https://fanyi.caiyunapp.com")
req.Header.Set("Referer", "https://fanyi.caiyunapp.com/")
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/101.0.4951.54 Safari/537.36")
req.Header.Set("X-Authorization", "token:qgemv4jr1y38jyq6vhvi")
req.Header.Set("app-name", "xy")
req.Header.Set("os-type", "web")
req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"Windows"`)
// 3.client.Do() 发送请求,接收响应 response
resp, err := client.Do(req)
if err != nil { // 如果出错,先打印错误信息,然后直接退出进程
log.Fatal(err)
}
defer resp.Body.Close() // response的 body 也是一个流,为了避免资源泄露,需要加一个 defer 来手动关闭这个流
// 4.处理响应
bodyText, err := ioutil.ReadAll(resp.Body) // 读取body中的流数据,存入bodyText
if err != nil {
log.Fatal(err) // 如果出错,先打印错误信息,然后直接退出进程
}
fmt.Printf("%s\n", bodyText) // 打印响应体
}
1.2.3.生成请求消息体
-
生成请求消息体
- 前面的消息体,我们是写死的
{"trans_type":"en2zh","source":"good"},我们应该使用一个结构体保存数据 - 创建一个 结构体 DictRequest,包含三部分数据:从什么语言转成什么语言、要翻译的数据、登录用户的ID
- 然后把代码中,请求体先构建成一个DictRequest结构,然后再使用
json.Marshal()转成json
- 前面的消息体,我们是写死的
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string `json:"user_id"`
}
func main() {
client := &http.Client{}
// 请求体先构建成一个DictRequest结构,然后再使用 json.Marshal() 转成json
request := DictRequest{TransType: "en2zh", Source: "good"}
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("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)
}
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", bodyText)
}
1.2.4.解析响应消息体
- 发送请求后,得到的响应体,为了方便后续使用,我们需要创建一个结构体 DictResponse,封装响应体数据
- 可 响应体内容太多了,手动创建结构体 麻烦费时还易出错,因此可以使用 工具 将响应体json转成Golang结构体
- 打开网址:oktools.net/json2go,输入响应体数据,点击转换-嵌套,即可生成 结构体,改名为 DictResponse 即可
- 然后在程序最后,将得到的响应体数据,使用
json.Unmarshal()封装成 DictResponse 结构,方便使用
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string `json:"user_id"`
}
// 1、工具生成结构体,改名为 DictResponse
type DictResponse 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 main() {
client := &http.Client{}
request := DictRequest{TransType: "en2zh", Source: "good"}
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("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)
}
defer resp.Body.Close()
bodyText, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Fatal(err)
}
// 2.将得到的响应体数据,封装成 DictResponse 结构
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse) // 注意使用取地址符号,直接操作结构体
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", dictResponse)
}
1.2.5.封装方法,封装可执行程序
- 将上述代码封装成方法
query(word string),需要一个参数,就是待翻译的文本 - 主方法,可以采用 命令行参数 传入参数,os.Args[0]表示当前执行的可执行文件,那么可以在os.Args[1]的位置传入参数。
- 主方法获取os.Args[1],如果获取成功,则作为 query() 的参数,调用query()查询结果并打印
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"`
}
type DictResponse 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"`
}
// 1.将上述代码封装成方法 `query(word string)`,需要一个参数,就是待翻译的文本
func query(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("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)
}
defer resp.Body.Close()
bodyText, err := ioutil.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(word, "UK:", dictResponse.Dictionary.Prons.En, "US:", dictResponse.Dictionary.Prons.EnUs)
for _, item := range dictResponse.Dictionary.Explanations {
fmt.Println(item)
}
}
// 2.主方法获取os.Args[1],如果获取成功,则作为 query() 的参数,调用query()查询结果并打印
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)
}
- 在终端运行命令