golang基础:GoLang基础学习 | 青训营笔记

198 阅读4分钟

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

JSON处理

json的场景应用

image.png

json数据格式

在json中一切皆为对象,一切数据(字符串,数字,字母,自定义对象等)都可以同json来表示;JSON用键值对的方式保存数据;

json解析

package main
import(
	"fmt"
	"encoding/json"
	//首先导入json工具的包
)
type user struct{
	Name string
	Age int
	Hobby []string
}
func main(){
	var a user
	a.Name="张三"
	a.Age=19
	a.Hobby=[]string{"golang","java","game"}
	buf,err:=json.Marshal(a)//进行序列化
	if err==nil {
		fmt.Println(string(buf))//转化为字符串的json数据
	}
	fmt.Println(a)
	buf,err=json.MarshalIndent(a,"","\t")
	//类似Marshal但会使用缩进将输出格式化
	if err==nil {
		fmt.Println(string(buf))
	}
}

输出结果:

{"Name":"张三","Age":19,"Hobby":["golang","java","game"]}
{张三 19 [golang java game]}
{
        "Name": "张三",
        "Age": 19,
        "Hobby": [
                "golang",
                "java",
                "game"
        ]
}

go发送http请求并解析json

首先发送http请求需要导入的包有io/ioutillognet/httpstrings; 步骤:

  1. 首先创建一个http连接:client := &http.Client{}
  2. 创建一个只读的读取数据的Reader,并在里面赋予一些参数:
var data = strings.NewReader(`{"trans_type":"en2zh","source":"good"}`)
  1. 创建一个request请求:
req, err := http.NewRequest("POST", "https://api.interpreter.caiyunai.com/v1/dict", data)

第一个参数是请求方式(get/post等),第二个参数是请求地址,第三个参数昂就是上面创建的Reader

  1. 之后根据要求在自己设置这个request请求的请求头的各项信息

  2. http连接发送这个request请求:resp, err := client.Do(req)响应是resp,如果报错的话err!=nil;

  3. 通过resp的响应码resp.StatusCode判断请求是否成功,成功的话响应码就是200;

  4. 如果请求成功的话我们就就可以写一个结构体将返回的json串反序列化到结构体里面,这样就是易读的信息了;

  5. 最后为了响应数据泄露我们需要关闭这个流defer resp.Body.Close()

socks5代理服务器

socks5代理服务器由于它的协议都是明文传输的,所以它不能用来翻墙,socks5就相当于在防火墙开了个小口子,用户可以根据单个端口去访问内部的所有资源,使访问某些资源不再那么麻烦;

socks5代理服务器原理

大致过程是浏览器先和socks5代理建立TCP连接,然后socks5代理再和真正的服务器建立TCP连接。这里可以分成四个阶段,握手阶段、认证阶段、请求阶段、relay阶段:

  1. 握手阶段,浏览器会向socks5代理发送请求,包的内容包括—个协议的版本号,还有支持的认证的种类,socks5服务器会选中—个认证方式,返回给浏览器。如果返回的是00的话就代表不需要认证,返回基他类型的话会开始认证流程。
  • 认证阶段略
  1. 请求阶段,认证通过之后浏览器会socks5代理服务器发起请求。主要信息包括版本号请求类型,一般主要是connection请求,代表socks5代理服务器要和某个域名或者某个IP地址某个端口建立TCP连接。代理服务器收到响应之后,会真正和后端服务器建立连接,然后返回一个响应。

  2. relav阶段。此时浏览器会正常发送请求,然后代理服务器接收到请求之后,会直接把请求转换到真正的服务器上。如果真正的服务器返回响应的话,那么也会把请求转发到浏览器这边。实际上代理服务器并不关心流量的细节,可以是HTTP流量,也可以是其它TCP流量。

写一个简单的TCP echo server实现

package main
import(
	"bufio"
	"log"
	"net"
)
//bufio包实现了有缓冲的I/O。
//它包装一个io.Reader或io.Writer接口对象,
//创建另一个也实现了该接口,且同时还提供了缓冲
//和一些文本I/O的帮助函数的对象。
func process(conn net.Conn){
	defer conn.Close()//关闭连接
	reader:=bufio.NewReader(conn)
	//NewReader创建一个具有默认大小缓冲,从conn读取的*Reader。
	for{
		b,err:=reader.ReadByte()
		//ReadByte读取并返回一个字节。如果没有可用的数据,会返回错误
		if err!=nil{
			break
		}
		_,err=conn.Write([]byte{b})
		//Write将p的内容写入缓冲。返回写入的字节数。
		//如果返回字节数<len(b),还会返回一个错误说明原因。
		if err!=nil{
			break
		}
	}
}
func main(){
	server,err:=net.Listen("tcp","127.0.0.1:1080")
	//创建一个tcp连接
	if(err!=nil){//判断连接是否出错
		log.Println("连接出错!!")
		panic(err)
	}
	for{
		client,err:=server.Accept();
		//持续接收请求,每次一个
		if(err!=nil){//判断是否接收成功
			log.Println("接收出错!!")
			panic(err)
		}
		go process(client)
		//开启一个子线程执行(可承受上万次并发)
	}
}