这是我参与「第三届青训营 -后端场」笔记创作活动的的第1篇笔记
go基础语言
简介十分钟
在golang里面不需要去寻找经过高度优化的第三方库,可以直接用官方库或者基于标准库的第三方来开发高并发,标准库很丰富
代码实现了简单http服务器
核心代码第八行在标准库的http包的路由,把\的路由指向静态文件
监听8080端口,启动服务器
编译结果是静态链接
云原生组件都是由go是实现的
入门
goproxy配置好后能加速第三方包
基础语法
属于mian包,main包是程序入口包,fmt是基础输入输出包
变量类型
字符是内置类型,可以用+和=使用,其他和c++类似
变量声明方式 var 名字 类型=..
或者变量名:=..
常量用const 自动确定类型
if 判断语句没有括号 在内部才有括号
循环里面用continue和break
c++里需要加break,go不需要
switch可以使用任意变量类型,包括使用字符串,结构体,可以省略if else
var 变量名[数量]类型
切片比数组更重要,不同于数组,他是可变数组
s := make([]string,3) 可是可变长度的
切片的append里面,原理存储了一个长度加一个容量和指向数组的指针,如果容量不够会扩容返回一个新的切片
slice里是左闭右开的
hash数组,key-value
map是无序的
slice和map用range遍历index-value,key-value
函数变量类型是后置的
指针就是对函数里的值修改
带类型 字段的集合
指针的结构体,可以进行值的修改
类似类成员函数,带指针可以对成员修改
用返回值来表示错误信息,可以确定到错误,直接return两个值,
字符串内置函数,对于中文来说一个中文对应多个字符
%v来打印结果 用%#v打印结构体类型
序列化后变成byte数组,需要用string()
注意输出的age和反序列化的处理
sub做时间段,格式化用2006-01-02 15:04:05的格式来确定自己的格式
解析字符串,parseint(111,10,64) 111表示字符串,10表示十进制,64表示精度,传0是自动推测
用atoi把字符串转成数字同理itoa相反
os.Args 获取进程的命令行参数 数出来的就是目录加参数
os.getenv获取环境变量
os.setenv写入环境变量
exec.Command快速启动子进程并获取输入输出
实战
随机生成数字
发现每次数组都是相同的,因为seed的参数一样
添加时间戳
stdin,stdout,stderro
用stdin来得到,直接操作不方便
bufio用只读流来读取一行,然后去掉换行符
atoi转换数字
用scanf会更好,因为bufio后面项目会用所以介绍一下
后面会添加循环
注意出错是continue
查询单词,并得到建议
原理:第三方api去查询翻译并打印,用go语言发送http请求,解析json,学习代码生成提高开发效率
尝试抓包看到了post请求,参数是json
介绍一个简单方式,生成请求
curlconverter.com/#go
把curl放入这个网站,同时删除错误
12行创建httpclient
可以指定参数的timeout,不超时
14行创建post请求,mehtod url data是一个流,流式数据
输出结果为json
把请求和返回都得到了
接下来需要序列化一个json 构建结构体,并调用json.marshal
结构体主要用了前两个,构造完结构体后,创建了一个结构体变量,然后json一下转化到byte的buf数组,然后转化为byte的data,变成byte流,同时执行结果不变
解析response,body返回的字典或者map,但是golang一般用结构体来对应response,再反序列化
用代码生成创建json结构体
oktools.net/json2go
把preview结构体放入,直接放入转换的嵌套结构体
定义dictResponse,并用json.Unmarshal来反序列化,注意要地址符,结果如下
91-93是防御式编程,需要对response请求判断,StatusCode判断报文
99-102取出想要的字符串
main函数改成query函数,然后通过加入的字符来判断,判断os.Args[1]
SOCKS5代理服务器,不能支持翻墙,明文传输,用途内网确保安全性,访问资源麻烦
SOCKS5需要暴露一个端口来访问内部资源,开发爬虫会碰到ip限制,可以去找ip代理池,代理池协议式socks5协议
代码的最终结果,配置代理,会发现域名加端口
打开网页会输出url域名和端口
正常访问的网址,不经过代理服务器的话,需要和服务器建立tcp链接,三次握手,握手完成,发送http请求,然后返回http响应
设置代理服务器会变的复杂,首先浏览器和socks5建立tcp连接,然后socks5和真正服务器tcp连接
协商阶段,发送协议版本号,支持认证种类和socks5连接返回浏览器,跳过对认证流程描述,
然后进入请求阶段,包括协议版本号,请求类型,命令代理服务器某个域名和ip进行连接,然后建立与目标的连接
然后就是发送数据,给socks5,socks5发送数据然后响应,接下来式简单实现
实现简单的TCP echo server 发送啥就回复啥
先监听端口,返回的server,然后server接收请求返回连接,然后用go process里处理连接,是一个子协程
process实现,需要第一步保证最后退出关conn
创建只读流,用for循环来读一个字节,并把字节写入,28行看起来是一个一个字节的读,实际上底层实现是连续的读的
32行 是进行字节转化,用[]byte,写一个字节给服务器
用nc 连接 输入hello服务器会返回hello
实现协议第一阶段,参数由只读流和tcp连接,浏览器发送报文,读报文并操作读出来,然后按照协议返回一个包给浏览器
process把死循环去掉,然后调用auth函数
认证逻辑:一个包三个字段:协议版本号,methods,第三个是编码,0代表不认证,1代表用户密码
然后读报文,因为单字节可以用readbyte读一个字节,返回版本号,然后再读方法名字,用methodsize创建method缓冲区,然后打印,77行 协议会返回一个包,创建了一个包,返回版本和不需要认证
结果发现日志是正常答应,但是curl命令是不成功的
请求阶段代码试图读取浏览器发送的报文,类似auth的conncet函数
第一个地段是version 5,command表示请求,第三个字段是保留字段默认为0,第四个字段是atype目标对峙类型,ipv4,ipv6或者域名,然后根据类型分配长度,最后一个是端口号
读取四个字段,总共四个字节,如果ipv4还是直接放,如果是host要读取长度,然后再换
再用binary来解析整形数字,然后打印地址和端口号,回包就是,一般不使用
结果可以看到正常打印出来访问的ip地址和端口,这样可以实现连接双向转发数据
使用完后就可以建立tcp连接,连接后第一时间关闭连接,接下来建立浏览器和服务器的双向数据转发,过程是copy函数从src读数据,写到dst,双向转发需要两个go routine
第一个路径从用户浏览器拷贝到到底层服务器
第二个是底层服务器到用户浏览器
当前问题需要等待任意一个方向关闭连接菜种植,所以需要一个context机制,等待Ctx.done结束
只有调用cancel()才能关闭连接
最后可以用curl命令测试一下,日志会输出协商发送的东西
也可以用浏览器安装switchormega插件,新建一个情景模式,代理服务器选socks5,端口写1080,然后点击应用选项,再点击小圈圈,流量会通过显示