刘沙河 刘沙河
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希

花开半夏,半夏花开
首页
  • Go语言基础

    • 数据类型
    • 反射
    • Go指针
  • Go语言进阶

    • go泛型
    • go条件编译
    • cgo教程
    • Go协程调度原理及GPM模型
    • Go内存管理
    • Go垃圾回收机制
    • Go语言内存对齐
  • Go语言实现原理

    • channel 实现原理
    • slice 实现原理
    • map 实现原理
    • sync.Mutex 实现原理
    • 乐观锁CAS 实现原理
    • singlefight 实现原理
  • gin框架

    • gin中间件原理
    • gin路由原理
  • gorm

    • GORM介绍和使用
    • GORM_CURD操作指南
  • go测试

    • benchmark基准测试
    • pprof 性能分析
  • python进阶

    • Numpy&Pandas
    • celery分布式任务队列
  • Django

    • Django 常见命令
    • middleware中间件
    • Django缓存系统
    • Django信号系统
    • Django REST Framework
  • Flask

    • Flask基础知识总结
    • Flask-SQLAlchemy
  • 爬虫

    • aiohttp
    • scrapy框架
  • Mysql

    • Mysql存储引擎和索引
    • MySQL主从复制
    • Mysql读写分离
    • 数据库分库分表
    • Mysql锁
    • Mysql事务和MVCC原理
    • 分库分表带来的读扩散问题
  • Redis

    • redis基础和数据类型
    • redis主从架构
    • redis哨兵架构
    • redis集群模式
    • 如何保证缓存和数据库双写一致
    • redis底层数据结构
    • redis分布式锁
  • Elasticsearch

    • es基本概念
    • es基础语法
    • es倒排索引
  • etcd

    • Go操作etcd
    • Raft原理
    • etcd分布式锁
  • kafka

    • 消息队列MQ总结
    • kafka 概述及原理
    • kafka 消费问题记录
    • 零拷贝技术
    • kafka分区规范
  • RabbitMQ

    • rabbitMQ基础
    • Go操作rabbitmq
  • RocketMQ

    • 可靠消息队列 rocketMQ
  • Http&Https

    • http&https
    • TCP和UDP
    • Ping 原理
  • RPC

    • RPC初识
    • grpc初识和实现
  • gRPC

    • grpc 初识
    • grpc 上下文 metadata
    • grpc 健康检查
    • grpc keepalive
    • grpc 命名解析
    • grpc 中间件&拦截器
    • grpc 负载均衡
    • grpc 身份认证
    • grpc 超时重试
    • grpc 链路追踪
    • grpc-gw将gRPC转RESTfu api
    • grpc-gw自定义选项
  • protobuf

    • protobuf 进阶
    • protobuf 编码原理
  • Docker

    • Docker基础
    • Docker常用命令
    • Dockerfile
    • Docker-Compose
    • Docker多阶段构建
    • Docker Config 教程
    • Docker Swarm 教程
    • Docker Stack 教程
    • Docker Buildx 教程
  • k8s

    • k8s 基础概念
    • k8s 集群架构
    • k8s 工作负载
    • Pod 网络
    • Service 网络
    • 外部接入网络
    • 一张图搞懂k8s各种pod
    • k8s 存储抽象
    • mac快速启动k8s
    • 自制申威架构k8s-reloader
  • go-kit

    • go-kit初识
    • go-kit启动http服务
    • go-kit集成gin启动服务
    • go-kit集成grpc和protobuf
    • go-kit中间件
    • go-kit服务注册发现与负载均衡
    • go-kit限流和熔断
    • go-kit链路追踪
    • go-kit集成Prometheus
  • 设计模式

    • 初识设计模式
    • 创建型模式
    • 结构型模式
    • 行为模式
  • 数据结构

    • 时间轮
    • 堆、双向链表、环形队列
    • 队列:优先队列
    • 队列:延迟队列
  • 算法

    • 递归算法
    • 枚举算法
    • 动态规划
    • 回溯算法
    • 分治算法
    • 贪心算法
    • LRU和LFU
    • 一致性哈希
  • go语言基础

    • 反射
    • nethttp模块
      • 1. Client
        • 1.1 启动client
      • 2. Request
      • 3. Get和Post的区别
        • 3.1 发起GET请求
        • 3.2 发起Post请求
      • 4. curl工具
      • 5. 启动server服务
      • 常见错误码
    • Socket编程
    • 内置函数&库
    • Context
    • 正则表达式
    • 环境配置
    • GoPath和GoMod
    • 变量
    • 数据类型
    • 运算符
    • 数据类型相关操作
    • 基础语法
    • 函数&复合类型
    • go指针
    • 函数
    • 数组和切片
    • 结构体
    • 接口
    • 空结构体
    • 文件操作
    • 并发与通道
    • channel 原理和坑
  • go语言进阶

  • go语言实现原理

  • gin框架

  • gorm

  • go测试

  • Go语言
  • go语言基础
bigox
2021-03-23
目录

nethttp模块

  • Go语言内置的net/http包十分的优秀,

  • 压力测试数据

    # mac 配置 8核 16G内存
    # goland 多核模式
      16 threads and 200 connections
      Thread Stats   Avg      Stdev     Max   +/- Stdev
        Latency     5.75ms   14.07ms 224.91ms   90.89%
        Req/Sec     9.46k     6.90k  100.80k    80.15%
      4403567 requests in 30.09s, 596.34MB read
      Socket errors: connect 0, read 56, write 0, timeout 0
    Requests/sec: 146360.93 # 每秒并发数高达 14.6w  是sanic 10进程的3倍
    Transfer/sec:  19.82MB
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
  • HTTP客户端有两个非常重要的类型client和request

# 1. Client

  • Client 结构体共有四个成员
    1. Transport 指定独立单次HTTP请求的机制
    2. CheckRedirect 指定处理重定向策略
    3. Jar 指定cookie管理器
    4. Timeout 指定文本类型的执行请求的时间限制
import "time"

type Client struct {
	Transport RoundTripper
	CheckRedirect func(req *Request, via []*Request)error
	Jar CookieJar
	Timeout time.Duration

}
1
2
3
4
5
6
7
8
9
  • Client类型主要充当浏览器角色; 它拥有一下方法:
    • Do get和post都是基于do方法进行的封装
    • Head
    • Get
    • Post
    • PostForm
image-20211206214457663

# 1.1 启动client

image-20211206214745422

/*
 * @date: 2021/12/6
 * @desc: ...
 */

package main

import (
	"fmt"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

func main() {
	// 创建连接池
	transport := &http.Transport{
		DialContext: (&net.Dialer{
			Timeout:   30 * time.Second, // 连接超时
			KeepAlive: 30 * time.Second, // 长连接保持时间
		}).DialContext,
		MaxIdleConns:          100,              // 最大空闲连接
		IdleConnTimeout:       90 * time.Second, //空闲超时时间
    TLSHandshakeTimeout:   10 * time.Second, //tls 握手超时时间 (https使用)
		ExpectContinueTimeout: 1 * time.Second,  //100-continue状态码超时时间
	}
	// 创建客户端
	client := http.Client{
		Timeout:   time.Second * 30, // 请求超时时间
		Transport: transport,
	}
	// 请求数据
	resp, err := client.Get("http://127.0.0.1:8080/bye")
	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()
	// 读取body内容
	bds, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(bds))

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47

# 2. Request

  • request是对请求体的封装吗任何形式的http请求都可以由request来构造, 构造完成之后使用Client发送请求;

    type Request struct {
    	Method string		//请求方法
    	Url *url.URL 		//请求地址
    	Proto string 		//协议版本
    	Header Header 		//请求头
    	Body io.ReadCloser 	//请求体
    	Form url.Values 	//解析好的表单数据,包括URL字段的query参数和post或者put的表单数据
    	//...
    	
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 3. Get和Post的区别

  1. get是从服务器上获取数据, post是向服务器推送数据
  2. get和post传递参数的方式不同, get将参数放在url后面,post是将表单数据放在请求体中
  3. get数据不安全,用户提交的数据用户能看到, post对用户不可见;
  4. GET请求传输数据量很小, 而POST请求可以传输大量的数据
  5. POST传输数据可以通过设置编码的方式正确转化中文, 而GET请求传输的数据没有变化

# 3.1 发起GET请求

  1. 简单请求
  • 不带参数
package main

import (
	"fmt"
	"io"
	"io/ioutil"
	"net/http"
)

func main() {
	get, err := http.Get("http://www.baidu.com")
	if err != nil {
		fmt.Println("get error", err)
		return
	}
	defer func(Body io.ReadCloser) {
		fmt.Println("close error")
		err := Body.Close()
		if err != nil {
		}
	}(get.Body)
	all, err := ioutil.ReadAll(get.Body)
	if err != nil {
		fmt.Println("read error")
		return 
	}
	fmt.Println(string(all))

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  • 带参数

关于GET请求的参数需要使用Go语言内置的net/url这个标准库来处理。

func main() {
	apiUrl := "http://127.0.0.1:9090/get"
	// URL param
	data := url.Values{}
	data.Set("name", "小王子")
	data.Set("age", "18")
	u, err := url.ParseRequestURI(apiUrl)
	if err != nil {
		fmt.Printf("parse url requestUrl failed, err:%v\n", err)
	}
	u.RawQuery = data.Encode() // URL encode
	fmt.Println(u.String())
	resp, err := http.Get(u.String())
	if err != nil {
		fmt.Printf("post failed, err:%v\n", err)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("get resp failed, err:%v\n", err)
		return
	}
	fmt.Println(string(b))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

对应的Server端HandlerFunc如下:

func getHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	data := r.URL.Query()
	fmt.Println(data.Get("name"))
	fmt.Println(data.Get("age"))
	answer := `{"status": "ok"}`
	w.Write([]byte(answer))
}
1
2
3
4
5
6
7
8
  1. 自定义get 请求
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
)

func main() {
	client := &http.Client{}
	request, err := http.NewRequest("GET", "http://www.baidu.com", nil)
	if err != nil {
		fmt.Println(err)
	}
	response, err := client.Do(request)
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(response.StatusCode) // 响应码

	res, err := ioutil.ReadAll(response.Body)

	fmt.Println(string(res))  // 获取的代码

}

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26

# 3.2 发起Post请求

  1. 简单post请求
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

// net/http post demo

func main() {
	url := "http://127.0.0.1:9090/post"
	// 表单数据
	//contentType := "application/x-www-form-urlencoded"
	//data := "name=小王子&age=18"
	// json
	contentType := "application/json"
	data := `{"name":"小王子","age":18}`
	resp, err := http.Post(url, contentType, strings.NewReader(data))
	if err != nil {
		fmt.Printf("post failed, err:%v\n", err)
		return
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("get resp failed, err:%v\n", err)
		return
	}
	fmt.Println(string(b))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

对应的Server端HandlerFunc如下:

func postHandler(w http.ResponseWriter, r *http.Request) {
	defer r.Body.Close()
	// 1. 请求类型是application/x-www-form-urlencoded时解析form数据
	r.ParseForm()
	fmt.Println(r.PostForm) // 打印form数据
	fmt.Println(r.PostForm.Get("name"), r.PostForm.Get("age"))
	// 2. 请求类型是application/json时从r.Body读取数据
	b, err := ioutil.ReadAll(r.Body)
	if err != nil {
		fmt.Printf("read request.Body failed, err:%v\n", err)
		return
	}
	fmt.Println(string(b))
	answer := `{"status": "ok"}`
	w.Write([]byte(answer))
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
  1. 自定义post请求
package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

func main() {
	resq, err:= http.Post("http://www.baidu.com",
		"application/x-www-form-urlencoded",
		strings.NewReader("user=admin&pass=admin"))
	if err !=nil{
		fmt.Println(err)
	}
	defer resq.Body.Close()
	body, err:= ioutil.ReadAll(resq.Body)
	if err!=nil{
		fmt.Println(err)
	}
	fmt.Println(body)

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 4. curl工具

  • curl 是一个利用URL语法在命令行工作的文件传输工具, 一般称之为下载工具

  • Curl 基础命令

    
    curl URL // get请求获取页面, 如果是一个图片,将会下载图片
    curl -o URL // 下载到本地
    curl -i URL // 显示头信息
    curl -v URL // 显示一次http通信的整个过程
    curl -X POST --data "data=xxx" URL  //发送post请求
    curl --user-agent "[USER AGENT]" URL  // 添加useragent
    curl --cokie "cookie" URL //添加cookie
    curl --head "head" URL  //添加请求头
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

# 5. 启动server服务

  • 方式一

    package main
    
    import (
    	"fmt"
    	"math/rand"
    	"net/http"
    	"time"
    )
    
    func indexHandler(w http.ResponseWriter, r *http.Request) {
    	rand.Seed(time.Now().UnixNano())
    	randNum := rand.Intn(2)
    	if randNum == 0 {
    		time.Sleep(5 * time.Second)
    	}
    	fmt.Fprintf(w, "quick response")
    }
    
    func main() {
    	http.HandleFunc("/", indexHandler)
    	err := http.ListenAndServe(":8000", nil)
    	if err != nil {
    		panic(err)
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
  • 方式二:

    package main
    
    import (
    	"log"
    	"net/http"
    	"time"
    )
    
    const ADDR = "127.0.0.1:8080"
    
    func sayBay(w http.ResponseWriter, r *http.Request) {
    	time.Sleep(time.Second * 1)
    	_, err := w.Write([]byte("bye bye!"))
    	if err != nil {
    		return
    	}
    }
    
    func main() {
    	// 创建路由器
    	mux := http.NewServeMux()
    	// 设置路由规则
    	mux.HandleFunc("/bye", sayBay)
    	// 创建服务器
    	server := &http.Server{
    		Addr:         ADDR,
    		WriteTimeout: time.Second * 3,
    		Handler:      mux,
    	}
    	// 监听端口并提供服务
    	log.Println("starting http server at: " + ADDR)
    	log.Fatal(server.ListenAndServe())
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33

# 常见错误码

  • 200 成功状态吗
  • 301 临时重定向
  • 302 永久重定向
  • 400 客户端 语法错误
  • 401 客户端身份认证失败
  • 403 拒绝访问
  • 404 找不到资源
  • 500 服务器内部错误
  • 501 服务器不支持
  • 502 错误的网关
  • 503 服务器过载
  • 504 网关超时
  • 505 http协议错误
#Go#
上次更新: 2023/04/16, 18:35:33
反射
Socket编程

← 反射 Socket编程→

最近更新
01
go与http代理
05-24
02
自制申威架构k8s-reloader
12-06
03
Docker Buildx 教程
12-01
更多文章>
Theme by Vdoing | Copyright © 2020-2024 小刘扎扎 | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式