golang基础:基础语言|青训营笔记
这是我参与「第三届青训营 -后端场」笔记创作活动的的第一篇笔记
课前导学链接
【Go 语言原理与实践学习资料】第三届字节跳动青训营-后端专场
本节课内容为Go语言基础和三个小项目实战,课程代码在以下网址中
课程ppt链接
Go 的特点
-
高性能、高并发
-
语法简单、学习曲线平缓
实现可以承载静态文件访问的高性能服务器
package main import "net/http" func main() { // 在 http 标准库里面内建路由,将 / 映射到一个静态文件 处理的实现 http.Handle("/", http.FileServer(http.Dir("."))) // 增添 8080 端口,并且启动服务器 http.ListenAndServe(":8080", nil) } -
丰富的标准库
-
完善的工具链
内置单元测试框架
-
静态链接
在go语言里,所有的编译结果默认都是静态链接的,只要拷贝编译之后唯一一个可执行文件,不需要附属任何东西就能部署运行
-
快速编译
go语言拥有静态语言里面几乎最快的编译速度
-
跨平台
能在各种奇奇怪怪的 平台运行,在笔记本编译一个二进制文件,拷贝到路由器上运行,而无需配置交叉编译环境
-
垃圾回收
写代码的时候无需考虑内存的分配与释放
Go 语言基础
第一部分的内容基本可以在以下链接中找到,建议基础薄弱的同学阅读以下链接。
此外贴出一个我非常推荐的一个Go语言教程,Go语言之旅
小项目实战
项目一:猜谜游戏
第一个小项目猜数字游戏,这个项目比较简单,主要是联系一些基础语法使用,使用相应的包建议浏览官方文档,此项目用到了math/rand包。
注意:使用随机数要设置随机数种子,否则将导致随机数永远是同一个数
func main(){
maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNum := rand.Intn(maxNum)
fmt.Println("the secret number is :", secretNum)
}
项目二:简单词典
第二个小项目简单词典,利用彩云小译的查词API来查询英语单词。
首先展示了如何利用浏览器开发人员工具获取HTTP请求的详细信息(网络部分找到dict请求),复制dict请求的cURL命令后,接着利用以下网站将相应的cURL命令转换为Go语言代码。
对于请求结果的处理需要在Go中创建相应的结构体,手动编写非常麻烦,这里利用以下在线工具中的json2go工具直接生成对应结构体。
这个项目整体难度也不大,但是其利用公共API的方式以及对于代码生成工具的利用非常值得学习。
项目三:SOCKS5代理
第三个小项目SOCKS5代理,这个项目代码量比前两个都要大也更为复杂,总计约200行。
首先简单介绍SOCK5代理的原理。
代码总共四个函数,main(),process(),auth(),connect(),主要部分是认证函数auth()和连接函数connect()。代码内容大多都是些读取数据,在各种数据格式之间进行转换。这里不进行赘述,建议自行查看源代码理解。
课后习题
题目一
修改第一个例子猜谜游戏里的最终代码,使用fmt.Scanf()来简化代码实现。
首先到官网查询fmt.Scanf()的文档,
其实也就跟C语言里的scanf用法差不多,只不过额外返回了一个error用于错误处理。
直接列出修改前后的代码
题目二
修改第二个例子命令行词典里的最终代码,增加另一种翻译引擎的支持。
使用有道翻译
结构体:
type YoudaoResp struct {
TranslateResult [][]struct {
Tgt string `json:"tgt"`
Src string `json:"src"`
} `json:"translateResult"`
ErrorCode int `json:"errorCode"`
Type string `json:"type"`
SmartResult struct {
Entries []string `json:"entries"`
Type int `json:"type"`
} `json:"smartResult"`
}
有道有防爬加密,需要构造请求参数
package main
import (
"crypto/md5"
"encoding/hex"
"encoding/json"
"fmt"
"io/ioutil"
"log"
"math/rand"
"net/http"
"os"
"strconv"
"strings"
"time"
)
func main() {
if len(os.Args) != 2 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1)
}
word := os.Args[1]
queryByYoudao(word)
}
func queryByYoudao(word string) {
t := time.Now().UnixMilli()
lts := strconv.FormatInt(t, 10)
rand.Seed(time.Now().UnixNano())
salt := lts + strconv.Itoa(rand.Intn(9))
sign := encrypt("fanyideskweb" + word + salt + "Ygy_4c=r#e#4EX^NUGUc5")
client := &http.Client{}
var data = strings.NewReader("i=" + word + "&from=AUTO&to=AUTO&smartresult=dict&client=fanyideskweb&salt=" + salt + "&sign=" + sign + "<s=" + lts + "&bv=d60b9bede0ddd264422f25a5e061c49a&doctype=json&version=2.1&keyfrom=fanyi.web&action=FY_BY_REALTlME")
req, err := http.NewRequest("POST", "https://fanyi.youdao.com/translate_o?smartresult=dict&smartresult=rule", data)
if err != nil {
log.Fatal(err)
}
req.Header.Set("Accept", "application/json, text/javascript, */*; q=0.01")
req.Header.Set("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8")
req.Header.Set("Cookie", "P_INFO=null; OUTFOX_SEARCH_USER_ID=-158590838@10.110.96.160; OUTFOX_SEARCH_USER_ID_NCOO=2106315215.8019254; DICT_UGC=be3af0da19b5c5e6aa4e17bd8d90b28a|; JSESSIONID=abcUFb505Z1AO_Umr8Ccy; ___rl__test__cookies=1651913317638")
req.Header.Set("Origin", "https://fanyi.youdao.com")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Referer", "https://fanyi.youdao.com/?keyfrom=dict2.top")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-origin")
req.Header.Set("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/100.0.4896.127 Safari/537.36")
req.Header.Set("X-Requested-With", "XMLHttpRequest")
req.Header.Set("sec-ch-ua", `" Not A;Brand";v="99", "Chromium";v="100", "Google Chrome";v="100"`)
req.Header.Set("sec-ch-ua-mobile", "?0")
req.Header.Set("sec-ch-ua-platform", `"macOS"`)
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 respEntity YoudaoResp
err = json.Unmarshal(bodyText, &respEntity)
if err != nil {
log.Fatal(err)
}
//fmt.Printf("%#v\n", respEntity)
fmt.Println(word, "SRC:", respEntity.TranslateResult[0][0].Src, "TGT:", respEntity.TranslateResult[0][0].Tgt)
for _, item := range respEntity.SmartResult.Entries {
fmt.Println(item)
}
}
func encrypt(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}
题目三
在上一步骤的基础上,修改代码实现并行请求两个翻译引擎来提高响应速度。
使用Go协程与WaitGroup来实现并发,只需对main()函数做一些修改如下
func main() {
if len(os.Args) != 3 {
fmt.Fprintf(os.Stderr, `usage: simpleDict WORD
example: simpleDict hello
`)
os.Exit(1)
}
w1 := os.Args[1]
w2 := os.Args[2]
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
queryCaiyun(w1)
}()
go func() {
defer wg.Done()
queryYoudao(w2)
}()
wg.Wait()
}
运行结果