Go知识查缺补漏+实战课程笔记 | 青训营笔记

1,492 阅读5分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记

分为简单基础语法的查缺补漏和最后实战项目的笔记

查缺补漏:

Map:

map的赋值是完全无序的,和插入的内容和插入顺序无关

结构体:

在方法中传入结构体指针作为参数,既可以起到修改作用,还有可以在某些情况下避免大结构体拷贝的开销

string库:

a := "hello"
fmt.Println(strings.Contains(a, "ll"))                // true
fmt.Println(strings.Count(a, "l"))                    // 2
fmt.Println(strings.HasPrefix(a, "he"))               // true
fmt.Println(strings.HasSuffix(a, "llo"))              // true
fmt.Println(strings.Index(a, "ll"))                   // 2
fmt.Println(strings.Join([]string{"he", "llo"}, "-")) // he-llo
fmt.Println(strings.Repeat(a, 2))                     // hellohello
fmt.Println(strings.Replace(a, "e", "E", -1))         // hEllo
fmt.Println(strings.Split("a-b-c", "-"))              // [a b c]
fmt.Println(strings.ToLower(a))                       // hello
fmt.Println(strings.ToUpper(a))                       // HELLO

fmt包:

+v:打印出更详细的内容

fmt.Printf("p=%+v\n", p) // p={x:1 y:2}

#v:打印出更更更加详细的内容

fmt.Printf("p=%#v\n", p) // p=main.point{x:1, y:2}

JSON:

序列化为一个字符串:

a := userInfo{Name: "wang", Age: 18, Hobby: []string{"Golang", "TypeScript"}}
	buf, err := json.Marshal(a)
	if err != nil {
		panic(err)
	}
	fmt.Println(buf)         // [123 34 78 97...]
	fmt.Println(string(buf)) // {"Name":"wang","age":18,"Hobby":["Golang","TypeScript"]}

反序列化回结构体:

var b userInfo
	err = json.Unmarshal(buf, &b)
	if err != nil {
		panic(err)
	}
	fmt.Printf("%#v\n", b) // main.userInfo{Name:"wang", Age:18, Hobby:[]string{"Golang", "TypeScript"}}

获取时间戳:

now := time.Now()
fmt.Println(now.Unix()) // 1648738080

类型转换:

这种方法老是忘记

//字符串转换为数字
n2, _ := strconv.Atoi("123") 
// 123

//数字转换为字符串
strconv.Itoa(n2)
// "123"

rand随机数

通过每次启动项目的时间生成的时间戳来生成对应的随机数种子:

maxNum := 100
rand.Seed(time.Now().UnixNano())
secretNumber := rand.Intn(maxNum)

客户端解析响应

将字符串转换成一个流

因为如果传入一个流而不是字符串,防止如果参数文件很大,将会浪费很多时间

client := &http.Client{}
var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)

补充自己之前写过的一篇博客(golang的Panic)

可以把panic理解为一种try catch

但是只用于捕获致命错误,而不应该用于报告普通错误:比如当某些不应该发生的场景发生时,我们就应该调用panic(数组越界、空指针异常等)

当发生异常并且被panic捕获时,程序会中断运行,然后执行defer

在go语言设计时,函数便搞上了一个多返回值,虽然十分冗杂,每次都要用if err != nil

但是,真要捕获异常并抛出,还得是用panic 实例代码

实战练习笔记:

SOCKS5代理服务器

SOCKS5协议是明文传输协议,用途是在防火墙中开一道口,让已经授权的用户通过单个端口有能力去访问其中的资源

启动效果:

​ 启动程序后,

  • 方式一:在浏览器里面配置使用这个代理,此时我们打开网页,代理服务器的日志,会打印出你访问的网站的域名或者IP,这说明我们的网络流量是通过这个代理服务器的。
  • 方式二:在命令行去测试我们的代理服务器。我们可以用cur-soci5 +代理服务器地址,后面加一个可访问的URL,如果代理服务器工作正常的话,那么curt命令就会正常返回。

image-20220507153549982

socks5协议的工作原理

​ 正常浏览器访问一个网站,如果不经过代理服务器的话,就会先和对方的网站建立TCP连接,然后三次握手。握手完之后发起 HTTP请求,然后服务返回HTTP响应。

​ 如果设置了代理服务器,流程会变得复杂一些。首先是浏览器和socks5代理建立TCP连接,socks5代理再和真正的服务器建立TCP连接。这里可以分成四个阶段,握手阶段、认证阶段、请求阶段、relay阶段。 ​ 第一个握手阶段,浏资器会向socks5代理发送请求,请求包的内容包括一个协议的版本号,还有支持的认证种类 , socks5会选择一个认证方式,返回给浏览器。如果返回的是00的话就代表不需要认证,如果是返回其他类型的话就会开始认证流程。

(认证流程:第一步,浏览器会给代理服务器发送一个包,这个包有三个字段;第一个字段:version,也就是协议版本号,固定是5;第二个字段:methods,认证的方法数目;第三个字段:每个method的编码,0代表不需要认证,2代表用户名密码认证 此时,代理服务器还需要返回一个response,返回包包括两个字段,一个是version一个是method,也就是我们选中的鉴权方式。)

​ 第三个阶段是请求阶段,认证通过之后浏览器会 向socks5发起请求。主要信息包括版本号,请求的类型,一般主要是connection请求,代表希望socks5服务器去和某个域名或者某个IP地址某个端口建立TCP连接, 代理服务器收到响应后,就会和后端服务器建立连接,然后返回响应。 ​ 第四个阶段是relay阶段,此时的浏览器会发送正常发送请求,然后代理服务器接收到请求之后,会直接把请求转换到真正的服务器上。然后如果真正的服务器返回响应的话,也会把响应发送给代理服务器,代理服务器并不关心发送流量的细节,可以是HTTP流量,也可以是其它TCP流量。