这是我参与「第五届青训营 」伴学笔记创作活动的第1天,今天主要学习了go环境配置方法以及go语言基础,并跟着老师敲了三个项目来巩固语言特性。
开发环境的配置
1.go官网下载对应window版本的msi安装即可,安装过程会自动配置环境变量。
2.本次学习采用vscode来进行go语言的学习,vocode方面只需要下载一个go语言插件,以及附加的8个包即可正常编译。
GO语言特性相关
由于之前有C++和python的基础 我觉得go的入门还是蛮简单的。有以下需要注意的地方:
map相关
m := make(map[string]int)
m["one"] = 1
m["two"] = 2
fmt.Println(m) // map[one:1 two:2]
fmt.Println(len(m)) // 2
fmt.Println(m["one"]) // 1
fmt.Println(m["unknow"]) // 0
r, ok := m["unknow"]
fmt.Println(r, ok) // 0 false
delete(m, "one")
m2 := map[string]int{"one": 1, "two": 2}
var m3 = map[string]int{"one": 1, "two": 2}
fmt.Println(m2, m3)
使用range遍历,i是num的位置
for i, num := range nums {
sum += num
if num == 2 {
fmt.Println("index:", i, "num:", num) // index: 0 num: 2
}
函数相关
go语言函数定义的返回值写在后边,形参类型也写在后边
func exists(m map[string]string, k string) (v string, ok bool) {
v, ok = m[k]
return v, ok
}
结构体函数
写法比较特殊,需要反复观看
type user struct {
name string
password string
}
func (u user) checkPassword(password string) bool {
return u.password == password
}
func (u *user) resetPassword(password string) {
u.password = password
}
func main() {
a := user{name: "wang", password: "1024"}
a.resetPassword("2048")
fmt.Println(a.checkPassword("2048")) // true
}
err相关
和C语言类似,在项目里使用非常平凡,使用err来接受返回值,判断是否等于nil来进行排查。
u, err := findUser([]user{{"wang", "1024"}}, "wang")
if err != nil {
fmt.Println(err)
return
}
string相关
记录一下常用api,用到的时候查询即可
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.Println(len(a)) // 5
b := "你好"
fmt.Println(len(b)) // 6
GO的实例项目
猜数字
简单叙述一遍逻辑,首先定义一个随机数的最大值,然后使用rand函数来生成随机数(rand函数需要提前设置一个种子来保证每次的随机数不同,这里使用时间戳来代替),接着使用bufio函数来记录键盘的输入(键盘输入分为两个部分,一部分是字符另一个部分是回车),提取出对应的字符后使用strconv将字符类型转换成int类型打印出来,接着就是简单的比较逻辑提示用户继续猜测(使用死循环来处理逻辑部分,达到可以一直运行的状态)
简单的字典
网络爬虫类的不是很了解,就跟着敲了一遍,运行的时候没有成功。然后clone老师的仓库运行,也没成功就先不看了.
Proxy
SOCKS 是一种互联网协议,是 SOCKetS 的缩写,这种协议使用代理服务器在以 TCP/IP 通讯的客户端和服务器之间传输流量,而客户端在防火墙的后面,因此透过代理服务器达到穿过防火墙的目的。从技术上来说,SOCKS 使用代理服务器,让用户穿过防火墙访问网站。此外,网络流量经由代理服务器进行路由,进而隐藏用户的真实 IP 地址。可以简单概况成允许一个设备通过第三个设备向另一个设备发送数据。换句话说,这第三个设备将被称为SOCKS服务器或SOCKS代理。它创建与位于防火墙后面的任何其他服务器的连接,并在客户端和实际服务器之间交换网络数据包。
代码v1版本实现了一个简单的服务器与客户端通信的模型,使用net.listen来监听客户端的接入,如果有接入调用Accept来和客户端建立连接。使用go来开启一个协程处理与客户端的通信,主程序持续监听下一个客户端的到来。通信函数里使用defer conn.Close来回收资源,这一点比C++方便,可以自动回收,避免资源泄露,接着就简单的收发数据环节。
代码的v2版本实现了协议的认证阶段,实现一个空的auth函数,在process函数里面调用,再来编写auth函数的代码。认证阶段的逻辑是浏览器会给代理服务器发送一个包,然后这个包有三个字段, 第一个字段,version也就是协议版本号,固定是5 第二个字段,methods,认证的方法数目第三个字段每个method的编码,0代表不需要认证,2代表用户名密码认证
代码的v3版本实现了请求阶段,读取到携带URL或者IP地址+端口的包打印出来。接下来把这个地址和端口打印出来用于调试。收到浏览器的这个请求包之后,需要返回一个包,这个包有很多字段,但其实大部分都不会使用。第一个是版本号还是socket5。第二个,就是返回的类型,这里是成功就返回0第三个是保留字段填0第四个atype地址类型填1第五个,第六个暂时用不到,都填成0。一共4+4+2个字节,后面6个字节都是0填充。
代码的v4版本直接用net.dial 建立一个TCP连接 建立完连接之后,我们同样要加一个defer来关闭连接。 接下来需要建立浏览器和下游服务器的双向数据转发。 标准库的io.copy可以实现一个单向数据转发,双向转发的话,需要启动两个go vroutinue。
最后一个项目有点半懂,大多数节选于ppt里的逻辑,后续有时间再仔细研究研究。