GO入门-原理与实践 | 青训营笔记

100 阅读3分钟

这是我参与「第五届青训营 」笔记创作活动的第1天。

学习内容:

今天开始go语言的入门学习,首先根据青训营的课程学习了go语言的原理和三个项目的实战,因为第一次接触go,课后又阅读了Go语言圣经(中文版)进行补充。

课程内容:

本节课程主要分为三部分:

  1. Go 语言简介
  2. Go 语言开发入门,包括开发环境配置、基础语法、标准库
  3. Go 实战练习,包括三个实战项目

什么是go:

高并发、高性能;语法简单、学习曲线平缓;丰富的标准库;完整的工具链;静态链接;快速编译;跨平台;垃圾回收。

基础语法:

  1. 变量声明;有两种方式:var 变量名 (变量类型) = 变量值以及变量名 := 变量值。声明常量就把var改成const即可。
  2. if else条件语句;与其他语言类似,if的条件不必加括号,执行语句在花括号内,第一个花括号必须与if同行。
if 条件 {
    执行语句
}
  1. 循环;go没有while,只有for,最简单用for加花括号表示一个死循环。
for 变量声明; 终止条件; 变量改变{
    执行语句
}
  1. swich;与其他语言类似,条件变量不必加括号,不用添加break就可以跳过之后的执行语句;条件变量可以是任何类型,甚至可以省略,可以替换成if条件语句。
switch 条件变量 {
case1:执行语句
case2:执行语句
case3:执行语句
......
}
  1. 数组;与其他语言类似,在业务代码中不常用,一般用切片;
  2. 切片;可变长度,用make来定义切片名 := make(变量类型,初始长度),可以用append追加元素切片s = append(切片s,追加元素1,追加元素2,......),有类似python的切片操作。
  3. map;用make来定义map名 := make(map[键类型]值类型),通过方括号写入和读取键值对,使用delete删除某一键值对。在go中,map完全无序的,遍历输出是随机顺序。
  4. range;对一个数组使用range会返回两个值,一个索引,一个是值。
  5. 指针;用途有限,主要对一个变量进行改变。
  6. 结构体;结构体方法;有带指针和不带指针两种;

标准库:

  1. errors: 主要用来判断error是否存在(nil or not)。
  2. strings: 字符串操作。
  3. fmt: 字符串格式化;%v可以打印任何类型。
  4. json: 一个结构体可以处理成json字符串,也可以反序列化。
  5. time: 时间处理,常用time.Now()获取当前时间。获取date的格式是一个固定的时间。
  6. strconv:字符串和数字的转换。

实战项目:

猜数字游戏:

maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)
fmt.Println("Please input your guess")
reader := bufio.NewReader(os.Stdin)
for {
	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)
	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
	}
}

在线词典:

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))
}
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代理:

原理:客户端不直接与服务端连接。

捕获.PNG

总的来说,前两个实践项目是比较简单的,最后的代理稍难。