golang笔记13--go语言 http 及其它标准库

golang笔记13--go语言 http 及其它标准库

  • 1 介绍
  • 2 http及其它标准库
    • 2.1 http 标准库
    • 2.2 其它标准库
    • 2.3 gin 框架介绍
    • 2.4 为 gin 增加 middleware
  • 3 注意事项
  • 4 说明

1 介绍

本文继上文 golang笔记12–迷宫的广度优先搜索, 进一步了解 go 语言 http 及其它标准库,以及相应注意事项。
具体包括: http 标准库、其它标准库、gin 框架介绍、为 gin 增加 middleware 等内容。

2 http及其它标准库

2.1 http 标准库

go http 库功能比较完善,此处通过服务端 和 客户端两个层面进行案例说明。
服务端:

vim 13.1.1.go
package main

import (
	"fmt"
	"html"
	"net/http"
	_ "net/http/pprof"
	"sync"
)

type countHandler struct {
     
	mu sync.Mutex // guards n
	n  int
}

func (h *countHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     
	h.mu.Lock()
	defer h.mu.Unlock()
	h.n++
	fmt.Fprintf(w, "count is %d\n", h.n)
}

func main() {
     
	http.Handle("/foo", new(countHandler))

	http.HandleFunc("/bar", func(w http.ResponseWriter, r *http.Request) {
     
		fmt.Fprintf(w, "Hello, %q", html.EscapeString(r.URL.Path))
	})
	http.ListenAndServe(":8888", nil)
}
输出:
http://127.0.0.1:8888/foo
1 (多次访问,其值逐渐增加)
http://127.0.0.1:8888/debug/pprof 可以访问其各种性能数据,具体如下图;

对于较复杂的http服务,可以通过命令行pprof来收集数据,然后通过其 pprof 的 web 功能输出各个模块调用时间关系图;具体使用方式如下(30s 采集完成后可以通过交互界面的web功能输出对于关系图):
chapter13/13.1-1$ go tool pprof http://localhost:8888/debug/pprof/profile
Fetching profile over HTTP from http://localhost:8888/debug/pprof/profile
Saved profile in /home/xg/pprof/pprof.___go_build_learngo_chapter13_13_1_1.samples.cpu.001.pb.gz
File: ___go_build_learngo_chapter13_13_1_1
Type: cpu
Time: Feb 18, 2021 at 1:07pm (CST)
Duration: 30s, Total samples = 0 
No samples were found with the default sample value type.
Try "sample_index" command to analyze different sample values.
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) web
(pprof) quit

golang笔记13--go语言 http 及其它标准库_第1张图片
客户端:

package main

import (
	"fmt"
	"net/http"
	"net/http/httputil"
)

func serverV1() {
     
	resp, err := http.Get("http://www.imooc.com")
	if err != nil {
     
		panic(err)
	}
	defer resp.Body.Close()
	s, err := httputil.DumpResponse(resp, true)
	if err != nil {
     
		panic(err)
	}
	fmt.Printf("%s\n", s)
}

func serverV2() {
     
	// 获取手机版本的网页信息
	request, err := http.NewRequest(http.MethodGet, "http://www.imooc.com", nil)
	request.Header.Add("User-Agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1")
	resp, err := http.DefaultClient.Do(request)
	if err != nil {
     
		panic(err)
	}
	defer resp.Body.Close()
	s, err := httputil.DumpResponse(resp, true)
	if err != nil {
     
		panic(err)
	}
	fmt.Printf("%s\n", s)
}

func main() {
     
	// serverV1()
	serverV2()
}
输出:
serverV1 输出PC网页版本主页信息,内容过多此处省略
serverV2 输出手机网页版本主页信息,内容过多此处省略

2.2 其它标准库

go 语言中包含很多常见标准库,例如 bufio、log、encoding/json、regexp、time、strings|math|rand 等;可以直接在官网文档查看,也可以通过 godoc -http :8080 起一个本地文档服务器查看文档。

package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"os"
	"regexp"
	"strings"
)

func testBufio() {
     
	// 打印输入的每行字符串
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
     
		fmt.Println(scanner.Text()) // Println will add back the final '\n'
	}
	if err := scanner.Err(); err != nil {
     
		fmt.Fprintln(os.Stderr, "reading standard input:", err)
	}
}

func testLog() {
     
	fmt.Println("test log")
	log.Print("test log")
}

func testJson() {
     
	fmt.Println("test json")
	const jsonStream = `
    {"Name": "Ed", "Text": "Knock knock."}
    {"Name": "Sam", "Text": "Who's there?"}
    {"Name": "Ed", "Text": "Go fmt yourself!"}`
	type Message struct {
     
		Name, Text string
	}
	dec := json.NewDecoder(strings.NewReader(jsonStream))
	for {
     
		var m Message
		if err := dec.Decode(&m); err == io.EOF {
     
			break
		} else if err != nil {
     
			log.Fatal(err)
		}
		fmt.Printf("%s: %s\n", m.Name, m.Text)
	}
}

func testRegexp() {
     
	fmt.Println("test regexp")
	matched, err := regexp.MatchString(`foo.*`, "seafood")
	fmt.Println(matched, err)
	matched, err = regexp.MatchString(`bar.*`, "seafood")
	fmt.Println(matched, err)
	matched, err = regexp.MatchString(`a(b`, "seafood")
	fmt.Println(matched, err)
}

func main() {
     
	//testBufio()
	testLog()
	testJson()
	testRegexp()
}
输出:
test log
2021/02/18 14:23:52 test log
test json
Ed: Knock knock.
Sam: Who's there?
Ed: Go fmt yourself!
test regexp
true <nil>
false <nil>
false error parsing regexp: missing closing ): `a(b`

2.3 gin 框架介绍

Gin 是使用go写的一个web 框架,其具备很高性能,比 httprouter 快40倍。

1) 安装方法
go get -u github.com/gin-gonic/gin
2) 案例
vim 13.3.go
package main

import "github.com/gin-gonic/gin"

func main() {
     
	r := gin.Default()

	r.GET("/ping", func(c *gin.Context) {
     
		c.JSON(200, gin.H{
     "message": "pong"})
	})
	r.Run(":8888")
}
输出:
http://127.0.0.1:8888/ping
{
     "message": "pong"}

2.4 为 gin 增加 middleware

本案例使用 middleware ,对每个请求都打印相关的日志,并记录每次请求所发的时间;

本案例依赖 gin 和 zap 的log模块
go get -u github.com/gin-gonic/gin
go get -u go.uber.org/zap
vim 13.4.go

package main

import (
	"math/rand"
	"time"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

const keyRequestId = "requestId"

func main() {
     
	r := gin.Default()
	logger, err := zap.NewProduction()
	if err != nil {
     
		panic(err)
	}
	r.Use(func(c *gin.Context) {
     
		s := time.Now()
		c.Next()
		logger.Warn("incoming request", zap.String("path", c.Request.URL.Path), zap.Int("status", c.Writer.Status()), zap.Duration("elapsed", time.Now().Sub(s)))
	}, func(c *gin.Context) {
     
		c.Set(keyRequestId, rand.Int())
		c.Next()
	})
	r.GET("/ping", func(c *gin.Context) {
     
		h := gin.H{
     "message": "pong"}
		if rid, exists := c.Get(keyRequestId); exists {
     
			h[keyRequestId] = rid
		}
		c.JSON(200, h)
	})
	r.GET("/hello", func(c *gin.Context) {
     
		c.String(200, "hello golang")
	})
	r.Run(":8888")
}
输出:
http://127.0.0.1:8888/ping
{
     "message": "pong","requestId": 605394647632969758}
http://127.0.0.1:8888/hello
hello golang

3 注意事项

  1. debug http 性能情况时,需要使用 _ “net/http/pprof” (前面需要添加一个下横杠,以确保该server 具备 pprof 等功能,不添加会导致保存时候被idea删除)

4 说明

  1. 软件环境
    go版本:go1.15.8
    操作系统:Ubuntu 20.04 Desktop
    Idea:2020.01.04
  2. 参考文档
    golang 轻量级框架 --Gin入门
    github gin 官方文档

你可能感兴趣的:(Golang,golang,go,http,gin,web框架,gin,middleware)