这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记。
前置学习资料
一、课前预习链接
【Go 语言原理与实践学习资料】第三届字节跳动青训营-后端专场 - 掘金 (juejin.cn)
二、课程PPT链接
Go 语言上手 - 基础语言.pptx - 飞书文档 (feishu.cn)
三、课程github链接
wangkechun/go-by-example (github.com)
四、Go语言基础知识
清华学神尹成带你实战Golang2022-go语言最新go1.17最有深度最详细-没有之一(开课吧golang试看视频)_哔哩哔哩_bilibili
实操项目
一、三个练手级项目(windows环境):
- 猜数字
- 知识点:rand/math包、switch循环等基础巩固
//随机数需要使用的随机数种子rand.Seed(),不然会生成相同的随机数
func selectNumGame1() {
maxNum := 100
rand.Seed(time.Now().UnixNano())
selectNum := rand.Intn(maxNum)
// fmt.Printf("我们需要猜的数为%v\n", selectNum)
fmt.Printf("请输入0-100的整数:")
reader := bufio.NewReader(os.Stdin)
for {
input, err := reader.ReadString('\n')
HandleErr("reader.ReadString", err)
input = strings.TrimSuffix(input, "\r\n")
guess, err := strconv.Atoi(input)
HandleErr("strconv.Atoi", err)
fmt.Println("你猜测的数字是:", guess)
if guess > selectNum {
fmt.Println("你猜测的数字过大")
} else if guess < selectNum {
fmt.Println("你猜测的数字过小")
} else {
fmt.Println("猜对了!")
break
}
}
}
func HandleErr(when string, err error) {
if err != nil {
fmt.Println(err, when)
return
}
}
- 在线翻译
- 知识点:json序列化与反序列化、命令行编程、爬虫(可选)等基础巩固
//根据payload创建对应的结构体字段
type DictRequest struct {
TransType string `json:"trans_type"`
Source string `json:"source"`
UserID string `json:"user_id,omitempty"`
}
//复制response的json自动生成go结构体
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"`
}
//根据复制的curl as bash生成对应的请求代码
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("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,ja;q=0.5")
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.41 Safari/537.36 Edg/101.0.1210.32")
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", "Microsoft Edge";v="101"`)
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 := 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)
}
}
- SOCKS5代理
- 知识点:socket编程、并发编程
-
使用工具:
-
原理图示:
SOCKS5交互流程: 1.当 TCP 客户端想要建立必须透过防火墙(取决于具体的情况)的连接时,客户端必须与合适的 SOCKS 服务建立连接。SOCKS 服务默认监听 1080 端口,如果连接成功,客户端需要与服务端协商认证方式并完成认证,之后便可以发送中继请求。SOCKS 服务端会执行请求,要么建立起合适的连接,要么拒绝请求。
2.一旦认证方法对应的协商完成,客户端就可以发送请求细节了。如果认证方法为了完整性或者可信性的校验,需要对后续请求报文进行封装,则后续请求报文都要按照对应规定进行封装。
3.SOCKS 服务端会根据请求类型和源、目标地址,执行对应操作,并且返回对应的一个或多个报文信息。回复报文,客户端与服务端建立连接并完成认证之后就会发送请求信息, 如果协商的方法为了完整性、可信性的校验需要封装数据包,则返回的数据包也会进行对应的封装。
4.当连接建立后,客户端就可以和正常一样访问服务端通信了,此时通信的数据除了目的地址是发往代理程序以外,所有内容都是和普通连接一模一样。对代理程序而言,后面所有收到的来自客户端的数据都会原样转发到服务读端。
-
- 知识点:socket编程、并发编程
//网络编程接口
func main() {
server, err := net.Listen("tcp", "127.0.0.1:1080")
if err != nil {
panic(err)
}
for {
client, err := server.Accept()
if err != nil {
log.Printf("Accept failed %v", err)
continue
}
go process(client)
}
}
二、课后习题
- 针对第一个项目,使用scanf方法简化代码
- 解题思路:考察的就是基础的循环语句的使用,比较简单,不多赘述
- 解题代码: ZiJieProject/2.作业.go at master · yyzyyyzy/ZiJieProject (github.com)
- 针对第二个项目,使用相同方法添加一个支持的搜索引擎
- 解题思路:考察的是网络编程相关,json序列化,爬虫等操作,难度相对第一题有所上升
- 解题代码一: ZiJieProject/2.1作业.go at master · yyzyyyzy/ZiJieProject (github.com)
- 解题代码二: ZiJieProject/3.谷歌翻译API.go at master · yyzyyyzy/ZiJieProject (github.com)
- 针对第二个项目,使用并发编程支持两个搜索引擎
- 解题思路:考察的是并发编程的基础知识,四种方法可供选择(time.Sleep、sync.WaitGroup、chan、context)
- 解题代码: ZiJieProject/2.2作业.go at master · yyzyyyzy/ZiJieProject (github.com)