03 实战
3.1 猜谜游戏
让用户猜一个0到100的整数,提示玩家猜测,不断告诉用户是高于还是低于这个数字,直到猜出该数字。
3.1.1 生成随机数
package main
import (
"fmt"
"math/rand"
)
func main() {
maxNum := 100
secretNumber := rand.Intn(maxNum)
fmt.Println("The secret number is", secretNumber)
}
- “math/rand”包表示随机数
- 不需要手动import,用相应的函数会自动import
- 代码文件顶部要声明
package main - 每次运行都可生成不同的随机数,与视频中所示不同
3.1.2 读取用户输入
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
)
func main() {
maxNum := 100
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 occuered 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("Your guess is", guess)
}
reader := bufio.NewReader(os.Stdin)
用于创建一个读取器(Reader),它可以从标准输入(os.Stdin)中读取数据。
input, err := reader.ReadString('\n')
从标准输入(通常是控制台)读取一行文本,直到遇到指定的分隔符(在这个例子中是换行符 \n)为止。
input = strings.Trim(input, "\r\n")
strings.Trim(input, "\r\n") 是一个字符串处理函数,它的作用是去除字符串 input 两端的指定字符。在这里,"\r\n" 是一个字符串,表示回车符(\r)和换行符(\n)。
- 输入功能可以用
scanf更简洁地实现该功能
3.1.3实现判断逻辑
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
)
func main() {
maxNum := 100
secretNumber := rand.Intn(maxNum)
//fmt.Println("The secret number is", secretNumber)
fmt.Println("Please input your guess")
//创建阅读器
reader := bufio.NewReader(os.Stdin)
//读入用户输入
for {
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("An error occuered 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("Your 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
}
}
}
Please input your guess
50
Your guess is 50
Your guess is bigger than the secret number. Please try again.
40
Your guess is 40
Your guess is bigger than the secret number. Please try again.
20
Your guess is 20
Your guess is bigger than the secret number. Please try again.
10
Your guess is 10
Correct, you Legend!
- 不可以在出错的时候return,而是要continue,让用户输入下一个值
3.2在线词典
调用第三方API,发送http请求
3.2.1抓包
彩云小译官网 - 高效准确的翻译工具 | 文字翻译 | 文档翻译 | 网页翻译 | 浏览器插件 | 双语对照 | 术语库
可能由于网站的更新,没有翻译按钮,也没有找到dict
代码生成:curl to Go
尝试了一个curl,但是报错了
3.2.2生成代码解读
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
func main() {
client := &http.Client{}
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)
}
//设置请求头
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)
}
输出json
需要让输入非固定
3.2.3生成request body
定义结构体,将结构体对象转换成json,作为data
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"net/http"
"strings"
)
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string 'json:"user_id"`'
}
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)
}
fmt.Printf("%s\n", bodyText)
}
3.2.4解析response body
把explainations,prons打印出来
需要定义一个结构体,把返回的json反序列化成结构体,然后得到想要的字段
json转golang struct:oktools.net,这个网站打不开,找了一个新的JSON转Golang结构体,但是用这个生成了好几个结构体,不能生成视频中所示的嵌套结构体
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"`
}
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)
}
//fmt.Printf("%s\n", bodyText)
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%#v\n", dictResponse)
}
3.2.5 打印结果
把source改成word,main函数改为query函数,word通过函数传进来,写一个新的main函数
打印单词音标,翻译
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"`
}
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))
}
//fmt.Printf("%s\n", bodyText)
var dictResponse DictResponse
err = json.Unmarshal(bodyText, &dictResponse)
if err != nil {
log.Fatal(err)
}
//fmt.Printf("%#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)
}
}
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)
}
- fmt.Fprintf(os.Stderr,
usage: simpleDict WORD example: simpleDict hello)
fmt.Fprintf 是一个格式化输出函数,它的作用是将格式化的字符串写入到指定的 io.Writer 接口的实现中。在这个例子中,os.Stderr 是标准错误输出的文件描述符,它通常用于输出错误信息。这行代码的作用是向标准错误输出打印一条格式化的帮助信息,告诉用户如何正确使用这个程序。具体来说,它打印了两行文本:
usage: simpleDict WORD
example: simpleDict hello
这两行文本告诉用户,这个程序的用法是在命令行中输入 simpleDict 后面跟着一个单词,例如 simpleDict hello
结果: