Go基础入门与实战 | 青训营笔记

102 阅读3分钟

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

Go语言的好处

  1. 高性能,高并发;堪比c,cpp
  2. 语法简单,上手快;
  3. 标准库可靠丰富
  4. 工具链完备,编译,格式化,错误检查,文档,测试等
  5. go编译之后全是静态链接,编译结果就是可执行文件;不像cpp需要管理动态库
  6. 增量编译,速度极快
  7. 跨平台友好
  8. 垃圾回收

Go基础语法

基础语法视频课程和文档已经很细致了,这里就不重复劳动了。

课程老师的仓库github.com/wangkechun/… 里面有完整的go基本语法的完整案例。

有一点强调一下:结构体的成员函数,必须是指针的形式才能对结构体内部的字段进行修改,否则只能读到值。如图:

image.png

项目实战代码

github.com/wangkechun/…

猜数字

主要有以下几个要点

  1. rand库生成随机数,需要给定Seed。
  2. bufio的缓存流式处理。
  3. strconv做转换字符串。

在线词典

这个项目的思路是做一个cli应用,从翻译api来获取翻译结果并解析打印输出。

主要涉及,http请求,json的序列化/反序列化,对应分别是net/http,encoding/json库。

其中提供了利用浏览器和网页工具快速生成请求代码的方法。

生成复杂请求:

  1. 通过浏览器开发者工具找到api的请求。
  2. 右键转化为cURL,拿到的curl访问的命令。
  3. curlconverter.com/go/ 这个网站提供了命令转成对应语言代码的功能。

生成复杂的解析response的代码:

  1. oktools.net/json2go 这个网站可以实现json转go代码。

其中两点需要强调:

  1. defer的用法,defer执行的时候是该语句当时的变量状态;defer一般直接跟在资源获取成功的后面写对资源进行释放的语句。
  2. log.Fatal(),这个函数老师没用讲,这个函数相当于执行os.Exit(1),打印完日志之后之后会直接结束程序。即defer什么的后面的通通不会再执行了。

proxy

这个项目是实现一个sock5代理。sock4代理的本质是将请求转发代理服务器,用户和目标服务器不直接通信,而是先和代理服务器认证建立连接,然后由代理服务器代劳和目标服务器进行通信。

本项目实现的是一个sock5的服务端程序,程序会开一个for循环不断监听作为服务。当有client访问代理服务器时,服务端处理该请求,先对客户端进行auth,解析其字段并验证有效性;然后进行连接,先解析获取到要访问的目标服务器的信息,然后通过net.Dial与目标服务器建立连接,建立成功后,通过原连接conn通知客户端sock5字段信息。

建立连接之后,要实现双向通信,需要代理服务端这里进行信息的转发。这里建立两个协程,通过io.Copy进行流缓存区的双向拷贝。

image.png 这里存在一个问题:如果不做处理,代码会直接运行到结束,connect协程会直接结束,这是违反逻辑的。我们需要在一方的行为发送异常后,认为连接中断。这里使用context的cancel机制来进行处理。

当两个协程中的一个停止之后,会执行cancel()函数关闭context。

// Done returns a channel that's closed when work done on behalf of this
// context should be canceled.
Done() <-chan struct{}

//  func Stream(ctx context.Context, out chan<- Value) error {
//  	for {
//  		v, err := DoSomething(ctx)
//  		if err != nil {
//  			return err
//  		}
//  		select {
//  		case <-ctx.Done():
//  			return ctx.Err()
//  		case out <- v:
//  		}
//  	}
//  }

看下官方给的这个示例:可以通过类似机制来控制stream的关闭。

本文同步知乎