这是我参与「第三届青训营 -后端场」笔记创作活动的的第 3 篇笔记
1. 使用 fmt.Scanf 来简化代码实现猜谜游戏
package main
import (
"fmt"
"math/rand"
"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")
//定义输入变量
var input string
for {
//使用 fmt.Scanf 来简化代码
_,err := fmt.Scanf("%s",&input)
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. 在线词典
我们先来看一下我们要用到的 API ,以彩云科技提供的在线翻译为例。先请打开彩云翻译的网页,然后右键检查打开浏览器的开发者工具。此时我们点一下翻译按钮,浏览器会发送一系列请求,我们能很轻松地找到那个用来查询单词的请求。这是一个 HTTP 的 post 的请求,请求的 header 的相当的复杂,有十来个。然后请求头是一个 json 里面有两个字段,一个是代表你要你是从什么语言转化成什么语言, source 就是你要查询的单词。 API 的返回结果里面会有 Wiki 和 dictionary 两个字段。我们需要用的结果主要在dictionary.Explanations 字段里面。其他有些字段里面还包括音标等信息。
我们需要在 Golang 里面去发送这个请求。因为这个请求比较复杂,用代码构造很麻烦,实际上我们有一种非常简单的方式来生成代码,我们可以右键浏览器里面的 copy as curl。 copy完成之后就可以在终端粘贴一下 curl 命令,应该可以成功返回一大串 json。
然后我们打开一个网站,粘贴 curl 请求,在右边的语言里面选 Golang 就能够看到一串很长的代码,我们直接把它 copy 到我们的编辑器里面。 有几个header比较复杂,生成代码有转义导致的编译错误,删掉这几行即可。
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)
}
我们来看一下这生成的代码,首先第 12 行我们创建了一个 HTTP client,创建的时候可以指定很多参数,包括比如请求的超时是否使用 cookie 等。接下来是构造一个 HTTP 请求,这是一个 post 请求,然后会用到 HTTP .NewRequest ,第一个参数是 http 方法 POST, 第二个参数是 URL, 最后一个参数是 body ,body因为可能很大,为了支持流式发送,是一个只读流。我们用了 strings.NewReader 来把字符串转换成一个流。这样我们就成功构造了一个 HTTP request ,接下来我们需要对这个 HTTP request 来设置一堆 header。
接下来我们把我们调用 client.do request ,就能得到 response 如果请求失败的话,那么这个 error 会返回非 nil,会打印错误并且退出进程。response 有它的 HTTP 状态码, response header和body。
body同样是一个流,在golang里面,为了避免资源泄露,你需要加一个 defer 来手动关闭这个流,这个 defer 会在这个函数运行结束之后去执行。接下来我们是用 ioutil.ReadAll 来读取这个流,能得到整个body。我们再用 print 打印出来。