net/http库学习

概念

处理器

  • 处理器:拥有ServeHTTP方法的接口(任何类型)

签名:ServeHTTP(http.ResponseWriter, *http.Request)

  1. ResponseWriter接口
  2. 指向Request结构的指针
  • ServeMux结构(拥有ServeHTTP方法,如上签名)
  • Handler结构
  • 多路复用器 DefaultServeMux(ServeMux结构的实例)

处理器函数

  • 与处理器有相同行为的函数

    • 与ServeHTTP方法有相同的签名

ServeMux

  • HTTP请求多路复用器

    • 接收HTTP请求__并根据请求中的__URL__将请求重定向到正确的__处理器
  • ServeMux结构也实现了ServeHTTP方法,它也是一个处理器
    • ServeMux的ServeHTTP方法,调用与被请求URL相对应的__处理器__的ServeHTTP方法

最简单的Web服务器

import "fmt"
import "net/http" // 处理器
type HelloHandler struct{}
func ( h *HelloHandler) ServeHTTP ( w http.ResponseWriter, r * http.Request){
fmt.Fprintf( w, "Hello" )
} // 处理器函数
func hello( w http.ResponseWriter, r * http.Request){
fmt.Fprintf( w, "Hello" )
} func main () {
server := http.Server{
Addr: "127.0.0.1:8080",
//Handler: nil, //可以指定处理器
}
fmt.Println("hello https://tool.lu/")
//http.ListenAndServe(":8181", nil)
//server.ListenAndServe() // 将 处理器 绑定到DefaultServeMux
// Handle是ServeMux结构的方法,而DefaultServeMux是ServeMux的实例
//hello := HelloHandler{}
//http.Handle("/hello", &hello) // 将函数转换为处理器,再将处理器绑定到DefaultServeMux
//http.HandleFunc( "/hello", hello ) //使用默认的多路复用器DefaultServeMux作为处理器
server.ListenAndServeTLS("cert.pem", "key.pem")
}

http客户端

http.NewRequest

  • htp.Client -> http.request(http.NewRequest) -> client.Do(request)
  • NewRequest(method, urlStr string, body io.Reader)

    • 第三个参数是请求的body中的内容
  • request.Header.Set
    • 向请求首部添加信息

http.Clinet

  • cient结构api

    • client.get/post/postform
  • client参数配置
    • Transport RoundTripper
    • CheckRedirect func(req Request, via []Request) error
    • Jar CookieJar
    • Timeout time.Duration
  • Transport
    • 为了控制代理、安全套接层设置、保持连接、压缩、超时设置和其它设定,需要创建一个Transport
    • MaxIdleConns
      • 对所有host的最大连接数量
    • MaxIdleConnsPerHost
      • 对__每个host__的最大连接数量
tr := &http.Transport{
TLSClientConfig: &tls.Config{RootCAs: pool},
DisableCompression: true,
}
client := &http.Client{Transport: tr}
resp, err := client.Get("https://example.com") tr := &http.Transport{
MaxIdleConnsPerHost: 1000, //是否表示最多建立1000个连接?
}
client := &http.Client{
Transport: tr,
}

http

  • http.Get/Post/Postform

resp.Body.Close()

  • 当客户端使用完response body后必须使用close对其进行关闭

httplib学习

https://github.com/astaxie/beego

概念

  • httplib库主要用来模拟客户端发送HTTP请求
  • 类似于curl工具

使用

  • request对象
  • debug输出
  • 设置clinet的TLS信息

gin学习

package tests

import (
"encoding/json"
"fmt"
"github.com/astaxie/beego/httplib"
"github.com/gin-gonic/gin"
"io/ioutil"
"log"
"net/http"
"strings"
"testing"
"time"
) func handleTestGet(c *gin.Context) {
c.String(http.StatusOK, "test get OK")
} func handleTestPost(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"code": 1, "message": "test post OK"})
} func handleParam(c *gin.Context) {
name := c.Param("name")
passwd := c.Param("passwd")
c.String(http.StatusOK, "name: %s, passwd: %s", name, passwd)
} func handleQuery(c *gin.Context) {
name := c.Query("name")
passwd := c.Query("passwd")
c.String(http.StatusOK, "name: %s, passwd: %s", name, passwd)
} func handleHTTPLib(c *gin.Context) {
c.IndentedJSON(200, gin.H{"code": 1, "data": "ok"})
} func runtBasicGinServer() {
fmt.Print("aa") router := gin.Default() router.GET("/test_get", handleTestGet)
router.POST("/test_post", handleTestPost) router.GET("/test_param/:name/*passwd", handleParam) router.GET("/test_query", handleQuery) router.GET("/test_httplib", handleHTTPLib) group := router.Group("/v1")
group.GET("/test_group", handleTestGet) router.Run(":6543")
} func printGetResp(resp *http.Response) {
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read body err %s\n", err.Error())
}
log.Printf("resp body is: %+v\n", string(bodyBytes))
} func printPostResp(resp *http.Response) {
defer resp.Body.Close()
bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read body err %s\n", err.Error())
}
type body struct {
Code int `json:"code"`
Message string `json:"message"`
}
respBody := body{}
err = json.Unmarshal(bodyBytes, &respBody)
if err != nil {
log.Printf("unmarshal body err %s\n", err.Error())
}
log.Printf("resp body is: %+v\n", respBody)
} func TestBasicClient(t *testing.T) {
go runtBasicGinServer()
time.Sleep(time.Second * 5)
resp, err := http.Get("http://127.0.0.1:6543/test_get")
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printGetResp(resp) resp, err = http.Post("http://127.0.0.1:6543/test_post", "", strings.NewReader(""))
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printPostResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_param/name=Bob/passwd=1234")
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_param/name=Bob/")
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_param/name=Bob")
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/test_query?name=Alice&passwd=123")
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printGetResp(resp) resp, err = http.Get("http://127.0.0.1:6543/v1/test_group")
if err != nil {
log.Printf("get resp err %s\n", err.Error())
}
printGetResp(resp) res := struct {
Code int `json:"code"`
Message string `json:"message"`
}{} if err := httplib.Get("http://127.0.0.1:6543/test_httplib").ToJSON(&res); err != nil {
log.Println(err.Error())
} log.Printf("%+v", res) } func TestReuseHTTPLink(t *testing.T) {
go runtBasicGinServer()
time.Sleep(time.Second * 5) tr := &http.Transport{
MaxIdleConnsPerHost: 100,
MaxIdleConns: 100,
}
c := http.Client{Transport: tr} url := "http://127.0.0.1:6543/test_get" /*
连接数,
当前 无剩余 可用连接时 会创建;
当前 有剩余 可用连接则 不创建
*/
// use channel to control http port numbers
ch := make(chan struct{}, 100) for i := 0; i < 5000; i++ {
go func(i int) {
ch <- struct{}{}
defer func() {
<-ch
}()
req, err := http.NewRequest("GET", url, nil) if err != nil {
log.Printf("get req error %s", err.Error())
}
resp, err := c.Do(req)
if err != nil {
log.Printf("do req error %s", err.Error())
}
defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read body error %s", err.Error())
} log.Printf("%d body: %s", i, string(bodyBytes))
}(i)
//time.Sleep(time.Microsecond * 50)
//time.Sleep(time.Microsecond * 50)
} time.Sleep(time.Second * 10)
} func TestSeqDo(t *testing.T) {
go runtBasicGinServer()
time.Sleep(time.Second * 5) c := http.Client{} url := "http://127.0.0.1:6543/test_get" /*
defaul reuse http link
there is one link to 6543
*/
for i := 0; i < 5000; i++ {
req, err := http.NewRequest("GET", url, nil) if err != nil {
log.Printf("get req error %s", err.Error())
}
resp, err := c.Do(req)
if err != nil {
log.Printf("do req error %s", err.Error())
}
defer resp.Body.Close() bodyBytes, err := ioutil.ReadAll(resp.Body)
if err != nil {
log.Printf("read body error %s", err.Error())
} log.Printf("%d body: %s", i, string(bodyBytes))
} time.Sleep(time.Second * 10)
} func TestSeqHTTPLib(t *testing.T) {
go runtBasicGinServer()
time.Sleep(time.Second * 5) url := "http://127.0.0.1:6543/test_get" /*
???netstat -anp | grep 6543 | grep ESTABLISHED
*/
for i := 0; i < 5000; i++ {
bodyString, err := httplib.Get(url).String()
if err != nil {
log.Printf("httplib get error %s", err.Error())
}
log.Printf("%d body: %s", i, bodyString)
} time.Sleep(time.Second * 10)
}

binding学习

github.com/gin-gonic/gin/binding

HTTPS服务

参考文献

《Go Web 编程》

Go语言_HTTP包

深入Go语言网络库的基础实现

golang中发送http请求的几种常见情况

Go语言net/http 解读

go net/http Client使用——长连接客户端的使用

https://github.com/astaxie/beego

beego中文文档

go语言 http学习的更多相关文章

  1. C语言课程学习的总结

    C语言课程学习的总结 学习C程序这门课一年了,这是我们学的第一门专业课.在大学里,C语言不但是计算机专业的必修课程而且也是非计算机专业学习计算机基础的一门必修课程.所以作为我这个计算机专业的学生来说当 ...

  2. [转]C语言指针学习经验总结浅谈

    指针是C语言的难点和重点,但指针也是C语言的灵魂 . 这篇C语言指针学习经验总结主要是我入职以来学习C指针过程中的点滴记录.文档里面就不重复书上说得很清楚的概念性东西,只把一些说得不清楚或理解起来比较 ...

  3. C语言(函数)学习之strstr strcasestr

    C语言(函数)学习之[strstr]&[strcasestr]一.strstr函数使用[1]函数原型char*strstr(constchar*haystack,constchar*needl ...

  4. 【Go语言】学习资料

    这段时间一直在看Go语言,6月3日Apple发布了swift发现里面竟然也有许多Go语言的影子,截至现在每天都在感觉到Go语言的强大.确实值得一学 今天在这里给园友们推荐一些Go语言的学习资料 网站 ...

  5. 远离go path,弃用go get,使用go mod 进行go语言的学习

    标题说的是go语言的学习,因为我也没做过开发 文章要解决的仅仅是一个问题 当你使用go get 无论如何get不到所需的包的问题 第一步就是下载goland 新手极其推荐goland,因为直接使用gl ...

  6. Dart语言快速学习上手(新手上路)

    Dart语言快速学习上手(新手上路) // 声明返回值 int add(int a, int b) { return a + b; } // 不声明返回值 add2(int a, int b) { r ...

  7. D02-R语言基础学习

    R语言基础学习——D02 20190423内容纲要: 1.前言 2.向量操作 (1)常规操作 (2)不定长向量计算 (3)序列 (4)向量的删除与保留 3.列表详解 (1)列表的索引 (2)列表得元素 ...

  8. D01-R语言基础学习

    R语言基础学习——D01 20190410内容纲要: 1.R的下载与安装 2.R包的安装与使用方法 (1)查看已安装的包 (2)查看是否安装过包 (3)安装包 (4)更新包 3.结果的重用 4.R处理 ...

  9. C++语言的学习环境

    一.Mac C++语言的学习环境 1. 1.1.C语言 :终端->bash-vi/vim文本编辑器->GNU->GCC文件编译器->a.out可执行文件 1.2.C++语言:终 ...

  10. 获奖感言和C语言的学习心得

    获奖感言和C语言的学习心得 自我介绍: 大家好,我的名字叫袁忠,我来自湖南,今年快19岁了,现在是大学一年级,我平时喜欢跑步.打羽毛球,我也喜欢学算法与数学,以及喜欢看一些与计算机有关的书籍,每次我学 ...

随机推荐

  1. Linux内核分析第六次作业

    分析system_call中断处理过程 一.先在实验楼的虚拟机中MenuOs增加utsname和utsname-asm指令. 具体实现如下: 1.克隆最新新版本的menu,之后进入menu 2.进入t ...

  2. Fiddler: 如何抓取HTTPS协议的网页

    作者:韦玮  转载请注明出处 Fiddler默认只能抓取HTTP协议的网页,不能抓取HTTPS协议的网页,而我们很多时候,都需要抓HTTPS协议的网页,比如抓淘宝数据等.今天,韦玮老师会为大家讲解如何 ...

  3. centos查看系统版本信息

    1.查看版本文件名称 ll /etc/*centos* 2.显示系统版本号 cat /etc/centos-release

  4. Batch Close process

    @echo offecho.rem Kill all chrome drivertaskkill /im chromedriver.exe /f pause

  5. OutOfMemoryError异常java内存泄漏(Memory Leak)和内存溢出(Memory Overflow)

    本篇文章理解源自于<深入理解java虚拟机>2.4章节 实战:OutOfMemoryError异常   在以下例子中,所有代码都可以抛出OutOfMemoryError异常,但是要区分到底 ...

  6. Java中运行时异常和非运行时异常什么鬼?

    Java中的异常分类 RuntimeException(也称unchecked exceptions,运行时异常) 就是我们在开发中测试功能时程序终止,控制台出现的异常.(一般来说,出现运行时异常基本 ...

  7. Kettle从excel导入数据到sql server

    从excel工作表中读取数据逐行执行insert语句插入到sqlserver 为了简单起见只选取了三个个字段作为参数,日期,字符类型的需要加上'' Spoon是作业配置的GUI界面,配置好后可以通过控 ...

  8. 优秀WordPress版微信小程序推荐(二)

    随着使用WordPress版微信小程序的用户越来越多,其中涌现不少优秀的小程序,无论UI设计还是功能上都远远超过我开源的程序.这次是推荐第二批优秀Wordpress版微信小程序,希望有更多的小程序的爱 ...

  9. centos7将可执行程序做成服务

    1.systemctl 用法:systemctl [OPT] COMMAND [NAME]…启动服务:systemctl start NAME.service停止服务:systemctl stop N ...

  10. [NOI2011]智能车比赛 (计算几何 DAG)

    /* 可以发现, 最优路径上的所有拐点, 基本上都满足一定的性质, 也就是说是在矩形上的拐角处 所以我们可以把他们提出来, 单独判断即可 由于我们提出来的不超过2n + 2个点, 我们将其按照x坐标排 ...