这是我参与「第五届青训营 」笔记创作活动的第1天
一、内容概览
- Go 语言环境搭建
- Windows 下 Go 环境搭建
- Linux 下 Go 环境搭建
- Go 语言基础语法
- Hello World!
- 其他
- 实战
- 猜谜游戏
- 在线词典
- SOCKS5 代理
二、知识点详解
1. Go 语言环境搭建
1.1 Windows 下 Go 环境搭建
-
1.1.1 安装 Golang
下载安装即可,安装过程勾选添加至系统环境变量,或者后续手动添加
-
1.1.2 测试是否安装成功 打开 Command Prompt
C:\Users\Chang>go version go version go1.19.5 windows/amd64 -
1.1.3 下载安装 GoLand
下载安装,后续打开工程,软件会自动检测 GOPATH
1.2 Linux 下 Go 环境搭建
- 1.2.1 下载压缩文件
$ wget https://studygolang.com/dl/golang/go1.19.5.linux-amd64.tar.gz $ ls go1.19.5.linux-amd64.tar.gz - 1.2.2 解压至指定路径
$ sudo tar -C /usr/local -xzf go1.19.5.linux-amd64.tar.gz [sudo] password for chang: $ cd /usr/local $ ls -l ··· drwxr-xr-x 10 root root 4096 Jan 10 06:41 go ··· - 1.2.3 建立 Go 工作空间
- src: 里面每一个子目录,就是一个包。包内是Go的源码文件
- pkg: 编译后生成的,包的目标文件
- bin: 生成的可执行文件
$ mkdir go $ ls go $ cd go $ mkdir src $ mkdir pkg $ mkdir bin $ ls bin pkg src $ chmod 777 src $ chmod 777 pkg $ chmod 777 bin - 1.2.4 设置环境变量
- 方法一
$ vi ~/.bashrc # Go environment export PATH=$PATH:/usr/local/go/bin export GOPATH=/home/chang/Projects/go $ source ~/.bashrc - 方法二
$ vi /etc/profile # Go environment export GOROOT=/usr/local/go export GOPATH=/home/chang/Projects/go export PATH=$PATH:$GOROOT/bin $ source $HOME/.profile
- 方法一
- 1.2.5 测试 Go 语言环境
$ go version go version go1.19.5 linux/amd64 $ go env ··· - 1.2.6 Hello World!
$ vi hello.go package main import "fmt" func main() { fmt.Printf("Hello World!\n") } $ go run hello.go Hello World! - 1.2.7 VS Code 配置
2. Go 基础语法
2.1 Hello World!
// hello.go
package main // 指定 hello.go 文件属于 main 包
import "fmt" // 导入标准库包
func main() { // main 函数, 程序入口
fmt.Printf("Hello World!\n") // 打印 Hello World!
}
go 的文件需指定所在的包,如本例中 package main 指定了 hello.go 文件属于 main 包,main 包有唯一的 main 函数,为程序入口,只有 main 包可编译成可执行文件。
2.2 基础语法
- 变量
- if-else
- for
- switch
- 数组
- 切片
- map
- range
- 函数
- 指针
- 结构体
- 结构体方法
- 错误处理
- 字符串操作
- 字符串格式化
- JSON 处理
- 时间处理
- 数字解析
- 进程信息
三、实践
1. 猜谜游戏
1.1 流程
- 生成随机数
- 读取用户输入
- 判断逻辑
- 游戏循环
1.2 代码实现
package main
import (
"bufio"
"fmt"
"math/rand"
"os"
"strconv"
"strings"
"time"
)
func main() {
// 1. 生成随机数
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) // 有缓冲的 I/O, 接收用户输入 【可简化】
// 4. 游戏循环, 用户不断猜测直到猜正确
for {
// 2. 读取用户输入
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) // 输入字符串类型转 int
if err != nil {
fmt.Println("Invalid input. Please enter an integer value")
continue
}
fmt.Println("You guess is", guess)
// 3. 判断逻辑
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
}
}
}
1.3 改进
fmt.Scanf 简化输入
package main
import (
"fmt"
"math/rand"
"time"
)
func main() {
var guess int
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
// fmt.Println("The secret number is ", secretNumber)
fmt.Println("Please input your guess")
for {
fmt.Scanf("%d", &guess)
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. 在线词典
2.1 知识点
- Go 发送 Http 请求
- 解析 JSON
- curl 请求生成为 Go 代码
2.2 流程
-
抓包:查看彩云小译翻译时发送的 request 及 response
-
curl 请求生成 go 代码
package main import ( "fmt" "io/ioutil" "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", "en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7") req.Header.Set("app-name", "xy") req.Header.Set("content-type", "application/json;charset=UTF-8") req.Header.Set("device-id", "") req.Header.Set("dnt", "1") 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", `"Not?A_Brand";v="8", "Chromium";v="108", "Microsoft Edge";v="108"`) 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/108.0.0.0 Safari/537.36 Edg/108.0.1462.76") req.Header.Set("x-authorization", "token:qgemv4jr1y38jyq6vhvi") 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) } -
request 的 json 序列化
上一步生成的 go http 请求代码的输入为固定的字符串输入,需要将输入修改为变量
type DictRequest struct { TransType string `json:"trans_type"` Source string `json:"source"` UserID string `json:"user_id"` } func main() { client := &http.Client{} // var data = strings.NewReader(`{"trans_type":"en2zh","source":"hello"}`) // json 序列化 request := DictRequest{TransType: "en2zh", Source: "hello"} 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) ··· } -
response 的 json 生成结构体
-
response 的 json 反序列化
package main import ( "fmt" "io/ioutil" "log" "net/http" "strings" ) type DictRequest struct { TransType string `json:"trans_type"` Source string `json:"source"` UserID string `json:"user_id"` } type DictResponse struct { ··· } func main() { client := &http.Client{} // json 序列化 request := DictRequest{TransType: "en2zh", Source: "hello"} 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) } ··· 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 反序列化 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.3 代码实现
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 {
···
}
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)
}
···
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)
}
}
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)
}
2.4 改进
- 增加另一种翻译引擎的支持
- 并行请求两个翻译引擎提高响应速度
3. SOCKS5 代理
四、总结
- Go 基础语法
- Go 发送 Http 请求
- curl 请求生成 go 代码
- json 生成 go 结构体
- SOCKS5 协议