博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
golang后端库gin笔记
阅读量:6758 次
发布时间:2019-06-26

本文共 12564 字,大约阅读时间需要 41 分钟。

Gin是Golang实现的一种web框架,基于httprouter

贴地址      https://github.com/gin-gonic/gin

快速开始

1下载安装

go get github.com/gin-gonic/gin

2代码导入

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

API示例

func main() {    // Creates a gin router with default middleware:    // logger and recovery (crash-free) middleware    router := gin.Default()    router.GET("/someGet", getting)    router.POST("/somePost", posting)    router.PUT("/somePut", putting)    router.DELETE("/someDelete", deleting)    router.PATCH("/somePatch", patching)    router.HEAD("/someHead", head)    router.OPTIONS("/someOptions", options)    // By default it serves on :8080 unless a    // PORT environment variable was defined.    router.Run()    // router.Run(":3000") for a hard coded port}复制代码

路径参数

func main() {    router := gin.Default()    // This handler will match /user/john but will not match neither /user/ or /user    router.GET("/user/:name", func(c *gin.Context) {        name := c.Param("name")        c.String(http.StatusOK, "Hello %s", name)    })    // However, this one will match /user/john/ and also /user/john/send    // If no other routers match /user/john, it will redirect to /user/john/    router.GET("/user/:name/*action", func(c *gin.Context) {        name := c.Param("name")        action := c.Param("action")        message := name + " is " + action        c.String(http.StatusOK, message)    })    router.Run(":8080")}复制代码

查询字段

router.GET("/welcome", func(c *gin.Context) {        firstname := c.DefaultQuery("firstname", "Guest")        lastname := c.Query("lastname")                         //c.Request.URL.Query().Get("lastname")        c.String(http.StatusOK, "Hello %s %s", firstname, lastname)    })复制代码

Multipart/Urlencoded表单提交

router.POST("/form_post", func(c *gin.Context) {        message := c.PostForm("message")        nick := c.DefaultPostForm("nick", "anonymous")        c.JSON(200, gin.H{            "status":  "posted",            "message": message,            "nick":    nick,        })    })复制代码

示例:查询参数+POST表单提交

POST /post?id=1234&page=1 HTTP/1.1Content-Type: application/x-www-form-urlencodedname=manu&message=this_is_great复制代码

func main() {    router := gin.Default()    router.POST("/post", func(c *gin.Context) {        id := c.Query("id")        page := c.DefaultQuery("page", "0")        name := c.PostForm("name")        message := c.PostForm("message")        fmt.Printf("id: %s; page: %s; name: %s; message: %s", id, page, name, message)    })    router.Run(":8080")}复制代码

id: 1234; page: 1; name: manu; message: this_is_great 复制代码

示例:上传文件

func main() {    router := gin.Default()    router.POST("/upload", func(c *gin.Context) {            file, header , err := c.Request.FormFile("upload")       //拿到上传的文件的信息            filename := header.Filename            fmt.Println(header.Filename)            out, err := os.Create("./tmp/"+filename+".png")            if err != nil {                log.Fatal(err)            }            defer out.Close()            _, err = io.Copy(out, file)                 //拷贝上传的文件信息到新建的out文件中            if err != nil {                log.Fatal(err)            }    })    router.Run(":8080")}复制代码

分组路由

func main() {    router := gin.Default()    // Simple group: v1    v1 := router.Group("/v1")                         {        v1.POST("/login", loginEndpoint)              //路由分组,访问地址变为:/v1/login        v1.POST("/submit", submitEndpoint)        v1.POST("/read", readEndpoint)    }    // Simple group: v2    v2 := router.Group("/v2")    {        v2.POST("/login", loginEndpoint)        v2.POST("/submit", submitEndpoint)        v2.POST("/read", readEndpoint)    }    router.Run(":8080")}复制代码

使用中间件

func main() {    // Creates a router without any middleware by default    r := gin.New()    // Global middleware               //全局中间件    r.Use(gin.Logger())    r.Use(gin.Recovery())    // Per route middleware, you can add as many as you desire.    r.GET("/benchmark", MyBenchLogger(), benchEndpoint)    //单个router中间件    authorized := r.Group("/")    // per group middleware! in this case we use the custom created    // AuthRequired() middleware just in the "authorized" group.    authorized.Use(AuthRequired())    {        authorized.POST("/login", loginEndpoint)        authorized.POST("/submit", submitEndpoint)        authorized.POST("/read", readEndpoint)        // nested group        testing := authorized.Group("testing")        testing.GET("/analytics", analyticsEndpoint)    }    // Listen and server on 0.0.0.0:8080    r.Run(":8080")}复制代码

model binding与验证

要绑定一个请求body到某个类型,可以使用model binding。目前支持JSON、XML以及from格式(foo=bar&boo=baz)的绑定

  • BindJSON(&json)
  • Bind(&form)

c.JSON(http.StatusUnauthorized,gin.H{"status":"unauthorized"})

// Binding from JSONtype Login struct {    User     string `form:"user" json:"user" binding:"required"`    Password string `form:"password" json:"password" binding:"required"`}func main() {    router := gin.Default()    // Example for binding JSON ({
"user": "manu", "password": "123"}) router.POST("/loginJSON", func(c *gin.Context) { var json Login if c.BindJSON(&json) == nil { //point1 if json.User == "manu" && json.Password == "123" { c.JSON(http.StatusOK, gin.H{
"status": "you are logged in"}) } else { c.JSON(http.StatusUnauthorized, gin.H{
"status": "unauthorized"}) } } }) // Example for binding a HTML form (user=manu&password=123) router.POST("/loginForm", func(c *gin.Context) { var form Login // This will infer what binder to use depending on the content-type header. if c.Bind(&form) == nil { if form.User == "manu" && form.Password == "123" { c.JSON(http.StatusOK, gin.H{
"status": "you are logged in"}) } else { c.JSON(http.StatusUnauthorized, gin.H{
"status": "unauthorized"}) } } }) // Listen and server on 0.0.0.0:8080 router.Run(":8080")}复制代码

Multipart/Urlencoded表单请求方式的绑定

测试命令:

curl -v --form user=user --form password=password http://localhost:8080/login 复制代码

package mainimport (    "github.com/gin-gonic/gin"    "github.com/gin-gonic/gin/binding")type LoginForm struct {    User     string `form:"user" binding:"required"`    Password string `form:"password" binding:"required"`}func main() {    router := gin.Default()    router.POST("/login", func(c *gin.Context) {        // you can bind multipart form with explicit binding declaration:        // c.BindWith(&form, binding.Form)        // or you can simply use autobinding with Bind method:        var form LoginForm        // in this case proper binding will be automatically selected        if c.Bind(&form) == nil {            if form.User == "user" && form.Password == "password" {                c.JSON(200, gin.H{
"status": "you are logged in"}) } else { c.JSON(401, gin.H{
"status": "unauthorized"}) } } }) router.Run(":8080")} 复制代码

XML和JSON的渲染   输出返回c.JSON()         c.XML()

func main() {    r := gin.Default()    // gin.H is a shortcut for map[string]interface{}    r.GET("/someJSON", func(c *gin.Context) {        c.JSON(http.StatusOK, gin.H{
"message": "hey", "status": http.StatusOK}) }) r.GET("/moreJSON", func(c *gin.Context) { // You also can use a struct var msg struct { Name string `json:"user"` Message string Number int } msg.Name = "Lena" msg.Message = "hey" msg.Number = 123 // Note that msg.Name becomes "user" in the JSON // Will output : {
"user": "Lena", "Message": "hey", "Number": 123} c.JSON(http.StatusOK, msg) }) r.GET("/someXML", func(c *gin.Context) { c.XML(http.StatusOK, gin.H{
"message": "hey", "status": http.StatusOK}) }) // Listen and server on 0.0.0.0:8080 r.Run(":8080")}复制代码

处理静态文件请求

func main() {    router := gin.Default()    router.Static("/assets", "./assets")    router.StaticFS("/more_static", http.Dir("my_file_system"))    router.StaticFile("/favicon.ico", "./resources/favicon.ico")    router.Run(":8080")}复制代码

HTML模板渲染

LoadHTMLGlob("/")

c.HTML()

func main() {    router := gin.Default()    router.LoadHTMLGlob("templates/*")    //router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")    router.GET("/index", func(c *gin.Context) {        c.HTML(http.StatusOK, "index.tmpl", gin.H{            "title": "Main website",        })    })    router.Run(":8080")} 复制代码

    

{
{ .title }}

复制代码

用自己的末班

import "html/template"func main() {    router := gin.Default()    html := template.Must(template.ParseFiles("file1", "file2"))    router.SetHTMLTemplate(html)    router.Run(":8080")}复制代码

用go-assets,编译一个服务端模板    https://github.com/jessevdk/go-assets

func main() {	r := gin.New()	t, err := loadTemplate()	if err != nil {		panic(err)	}	r.SetHTMLTemplate(t)	r.GET("/", func(c *gin.Context) {		c.HTML(http.StatusOK, "/html/index.tmpl",nil)	})	r.Run(":8080")}// loadTemplate loads templates embedded by go-assets-builderfunc loadTemplate() (*template.Template, error) {	t := template.New("")	for name, file := range Assets.Files {		if file.IsDir() || !strings.HasSuffix(name, ".tmpl") {			continue		}		h, err := ioutil.ReadAll(file)		if err != nil {			return nil, err		}		t, err = t.New(name).Parse(string(h))		if err != nil {			return nil, err		}	}	return t, nil}复制代码

重定向   

非常方便

r.GET("/test", func(c *gin.Context) {    c.Redirect(http.StatusMovedPermanently, "http://www.google.com/")})复制代码

定制中间件

核心c.Next()

func Logger() gin.HandlerFunc {    return func(c *gin.Context) {        t := time.Now()        // Set example variable        c.Set("example", "12345")        // before request        c.Next()        // after request        latency := time.Since(t)        log.Print(latency)        // access the status we are sending        status := c.Writer.Status()        log.Println(status)    }}func main() {    r := gin.New()    r.Use(Logger())    r.GET("/test", func(c *gin.Context) {        example := c.MustGet("example").(string)        // it would print: "12345"        log.Println(example)    })    // Listen and server on 0.0.0.0:8080    r.Run(":8080")}复制代码

中间件中的Goroutines

在middleware或者handler中使用goroutine时,不能直接使用gin.Context,只能用它的一份拷贝。       cCp := c.Copy()

func main() {    r := gin.Default()    r.GET("/long_async", func(c *gin.Context) {        // create copy to be used inside the goroutine        cCp := c.Copy()                                          //注意点        go func() {            // simulate a long task with time.Sleep(). 5 seconds            time.Sleep(5 * time.Second)            // note that you are using the copied context "cCp", IMPORTANT            log.Println("Done! in path " + cCp.Request.URL.Path)        }()    })    r.GET("/long_sync", func(c *gin.Context) {        // simulate a long task with time.Sleep(). 5 seconds        time.Sleep(5 * time.Second)        // since we are NOT using a goroutine, we do not have to copy the context        log.Println("Done! in path " + c.Request.URL.Path)    })    // Listen and server on 0.0.0.0:8080    r.Run(":8080")}复制代码

自定义HTTP配置

直接使用http.ListenAndServer(),示例

func main() {    router := gin.Default()    http.ListenAndServe(":8080", router)}复制代码

或者

func main() {    router := gin.Default()    s := &http.Server{        Addr:           ":8080",        Handler:        router,        ReadTimeout:    10 * time.Second,        WriteTimeout:   10 * time.Second,        MaxHeaderBytes: 1 << 20,    }    s.ListenAndServe()}复制代码

平滑重启或关闭

库名fvbock/endless,  来代替ListenAndServe

router := gin.Default()router.GET("/", handler)// [...]endless.ListenAndServe(":4242", router)复制代码

替代endless,可选择的有...,写一个得了

graceful

import (	"context"	"log"	"net/http"	"os"	"os/signal"	"time"	"github.com/gin-gonic/gin")func main() {	router := gin.Default()	router.GET("/", func(c *gin.Context) {		time.Sleep(5 * time.Second)		c.String(http.StatusOK, "Welcome Gin Server")	})	srv := &http.Server{		Addr:    ":8080",		Handler: router,	}	go func() {		// service connections		if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {			log.Fatalf("listen: %s\n", err)		}	}()	// Wait for interrupt signal to gracefully shutdown the server with	// a timeout of 5 seconds.	quit := make(chan os.Signal)	signal.Notify(quit, os.Interrupt)	<-quit	log.Println("Shutdown Server ...")	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)	defer cancel()	if err := srv.Shutdown(ctx); err != nil {		log.Fatal("Server Shutdown:", err)	}	log.Println("Server exiting")}复制代码

转载地址:http://agzeo.baihongyu.com/

你可能感兴趣的文章
STL容器的效率比较
查看>>
Ckeditor使用总结
查看>>
人事面试100问题--巧妙应答
查看>>
【工具类】怎么进入阿里云docker仓库
查看>>
Ceres-Solver库入门
查看>>
悲惨而又丢人的创业经历:草根创业者含恨倾诉为什么失败
查看>>
理解WebKit和Chromium: WebKit, WebKit2, Chromium和Chrome介绍
查看>>
hanoi塔的递归算法
查看>>
C# 校验给定的ip地址是否合法
查看>>
lumen 登陆 注册 demo
查看>>
基于服务的并行系统的通讯方式探讨
查看>>
设计模式——观察者模式
查看>>
Python多线程 简明例子
查看>>
《地球上的星星》
查看>>
mysql数据库的主从同步,实现读写分离
查看>>
89 fcanf和fprintf
查看>>
javascript——自定义右键菜单
查看>>
求二叉树中相差最大的两个节点间的差值绝对值
查看>>
PHP 类名::class含义
查看>>
设计模式简介和分类,重点在总结
查看>>