go之web框架gin

介绍

Gin 是一个用 Go (Golang) 编写的 Web 框架。 它具有类似 martini 的 API,性能要好得多,多亏了 httprouter,速度提高了 40 倍。 如果您需要性能和良好的生产力,您一定会喜欢 Gin。

安装

go get -u github.com/gin-gonic/gin

快速开始

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() // 监听并在 0.0.0.0:8080 上启动服务
}

接受请求参数

公共部分

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	router := gin.Default()
	 //调用方法
	router.Run(":8080")
}

get请求

获取路径上数据(post一样)

使用gin.Context.Query("参数名")获取

func main() {
	router := gin.Default()
	testGetUrl(router)
	router.Run(":8080")
}
func testGetUrl(router *gin.Engine) {
	router.GET("/getUrl", func(c *gin.Context) {
		// 获取参数值
		name := c.Query("name")
		age := c.Query("age")
		// 返回响应
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})
}

获取路由参数(post一样)

package main

import (
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	router := gin.Default()
	testRouteParams(router)
	router.Run(":8080")
}
func testRouteParams(router *gin.Engine) {
	router.GET("/routeParams/:name/:age", func(c *gin.Context) {
		// 获取参数值
		name := c.Param("name")
		age := c.Param("age")
		// 返回响应
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})
}

获取cookie(post一样)

package main

import (
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	router := gin.Default()
	testCookies(router)
	router.Run(":8080")
}
func testCookies(router *gin.Engine) {
	router.GET("/cookies", func(c *gin.Context) {
		// 获取参数值
		name, _ := c.Cookie("name")
		age, _ := c.Cookie("age")
		// 返回响应
		c.JSON(http.StatusOK, gin.H{
			"name": name,
			"age":  age,
		})
	})
}

获取表单参数(post一样)

func main() {
	router := gin.Default()
	testGetForm(router)
	router.Run(":8080")
}
func testGetForm(router *gin.Engine) {
	router.GET("/getForm", func(c *gin.Context) {
		var form User
		// 在这种情况下,将自动选择合适的绑定
		if c.ShouldBind(&form) == nil {
			// 返回响应
			c.JSON(http.StatusOK, gin.H{
				"name": form.Name,
				"age":  form.Age,
			})
		}

	})
}

获取请求头(post一样)

func main() {
	router := gin.Default()
	testGetHeader(router)
	router.Run(":8080")
}
func testGetHeader(router *gin.Engine) {
	router.GET("/getHeader", func(c *gin.Context) {
		// 获取参数值
		name := c.GetHeader("name")
		age := c.GetHeader("age")
		contentType := c.GetHeader("Content-Type")
		// 返回响应
		c.JSON(http.StatusOK, gin.H{
			"name":        name,
			"age":         age,
			"contentType": contentType,
		})
	})
}

post请求

获取请求体数据

和post表单一样

func main() {
	router := gin.Default()
	testPostForm(router)
	router.Run(":8080")
}
func testPostForm(router *gin.Engine) {
	router.POST("/postForm", func(c *gin.Context) {
		var form User
		// 在这种情况下,将自动选择合适的绑定
		if c.ShouldBind(&form) == nil {
			// 返回响应
			c.JSON(http.StatusOK, gin.H{
				"name": form.Name,
				"age":  form.Age,
			})
		}

	})
}

文件上传下载

上传单个文件

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	router := gin.Default()
	testUpload(router)
	router.Run(":8080")
}
func testUpload(router *gin.Engine) {
	// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
	router.MaxMultipartMemory = 8 << 20 // 8 MiB
	router.POST("/upload", func(c *gin.Context) {
		// 单文件
		file, _ := c.FormFile("file")
		dst := file.Filename
		// 上传文件至指定的完整文件路径
		c.SaveUploadedFile(file, dst)
		// 返回响应
		c.JSON(http.StatusOK, gin.H{
			"name": file.Filename,
		})
	})
}

上传多个文件

package main

import (
	"github.com/gin-gonic/gin"
	"net/http"
)

func main() {
	router := gin.Default()
	testUploadMany(router)
	router.Run(":8080")
}
func testUploadMany(router *gin.Engine) {
	// 为 multipart forms 设置较低的内存限制 (默认是 32 MiB)
	router.MaxMultipartMemory = 8 << 20 // 8 MiB
	router.POST("/uploadMany", func(c *gin.Context) {
		// Multipart form
		form, _ := c.MultipartForm()
		fileNames := make([]string, 0)
		files := form.File["fileList"]
		for _, file := range files {
			// 上传文件至指定目录
			c.SaveUploadedFile(file, "filedir/"+file.Filename)
			fileNames = append(fileNames, file.Filename)
		}
		// 返回响应
		c.JSON(http.StatusOK, gin.H{
			"name": fileNames,
		})
	})
}

下载文件

package main

import (
	"github.com/gin-gonic/gin"
	"io"
	"net/http"
	"net/url"
	"os"
)

func main() {
	router := gin.Default()
	testDownload(router)
	router.Run(":8080")
}
func testDownload(router *gin.Engine) {
	router.POST("/download", func(c *gin.Context) {
		// 获取文件路径
		targetFileName := "照片1.png"
		filePath := "filedir/" + targetFileName
		// 检查文件是否存在
		_, err := os.Stat(filePath)
		if os.IsNotExist(err) {
			c.String(http.StatusNotFound, "File not found")
			return
		}
		//中文名称会乱码,导致下载失败,所以需要编码
		name := url.QueryEscape(targetFileName)
		// 设置响应头,指定文件名和内容类型
		c.Header("Content-Disposition", "attachment; filename="+name)
		c.Header("Content-Type", "application/octet-stream")
		// 打开文件
		file, err := os.Open(filePath)
		if err != nil {
			c.String(http.StatusInternalServerError, "Error opening file")
			return
		}
		defer file.Close()
		// 将文件内容写入响应体
		_, err = io.Copy(c.Writer, file)
		if err != nil {
			c.String(http.StatusInternalServerError, "Error copying file")
			return
		}
	})
}

由于是postman下载的,没法解析为中文,用浏览器下载就没问题了

日志

func main() {
    // 禁用控制台颜色,将日志写入文件时不需要控制台颜色。
    gin.DisableConsoleColor()

    // 记录到文件。
    f, _ := os.Create("gin.log")
    gin.DefaultWriter = io.MultiWriter(f)

    // 如果需要同时将日志写入文件和控制台,请使用以下代码。
    // gin.DefaultWriter = io.MultiWriter(f, os.Stdout)

    router := gin.Default()
    router.GET("/ping", func(c *gin.Context) {
        c.String(200, "pong")
    })

    router.Run(":8080")
}

路由组

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

	// 简单的路由组: v1
	v1 := router.Group("/v1")
	{
		v1.POST("/login", loginEndpoint)
		v1.POST("/submit", submitEndpoint)
		v1.POST("/read", readEndpoint)
	}

	// 简单的路由组: v2
	v2 := router.Group("/v2")
	{
		v2.POST("/login", loginEndpoint)
		v2.POST("/submit", submitEndpoint)
		v2.POST("/read", readEndpoint)
	}

	router.Run(":8080")
}

运行多个服务

package main

import (
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"golang.org/x/sync/errgroup"
)

var (
	g errgroup.Group
)

func router01() http.Handler {
	e := gin.New()
	e.Use(gin.Recovery())
	e.GET("/", func(c *gin.Context) {
		c.JSON(
			http.StatusOK,
			gin.H{
				"code":  http.StatusOK,
				"error": "Welcome server 01",
			},
		)
	})

	return e
}

func router02() http.Handler {
	e := gin.New()
	e.Use(gin.Recovery())
	e.GET("/", func(c *gin.Context) {
		c.JSON(
			http.StatusOK,
			gin.H{
				"code":  http.StatusOK,
				"error": "Welcome server 02",
			},
		)
	})

	return e
}

func main() {
	server01 := &http.Server{
		Addr:         ":8080",
		Handler:      router01(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}

	server02 := &http.Server{
		Addr:         ":8081",
		Handler:      router02(),
		ReadTimeout:  5 * time.Second,
		WriteTimeout: 10 * time.Second,
	}

	g.Go(func() error {
		return server01.ListenAndServe()
	})

	g.Go(func() error {
		return server02.ListenAndServe()
	})

	if err := g.Wait(); err != nil {
		log.Fatal(err)
	}
}

重定向

HTTP 重定向很容易。 内部、外部重定向均支持。

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

通过 POST 方法进行 HTTP 重定向。请参考 issue:#444

r.POST("/test", func(c *gin.Context) {
	c.Redirect(http.StatusFound, "/foo")
})

路由重定向,使用 HandleContext

r.GET("/test", func(c *gin.Context) {
    c.Request.URL.Path = "/test2"
    r.HandleContext(c)
})
r.GET("/test2", func(c *gin.Context) {
    c.JSON(200, gin.H{"hello": "world"})
})
相关推荐
许野平25 分钟前
Rust: 利用 chrono 库实现日期和字符串互相转换
开发语言·后端·rust·字符串·转换·日期·chrono
也无晴也无风雨28 分钟前
在JS中, 0 == [0] 吗
开发语言·javascript
狂奔solar36 分钟前
yelp数据集上识别潜在的热门商家
开发语言·python
blammmp1 小时前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧1 小时前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
暗黑起源喵2 小时前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong2 小时前
Java反射
java·开发语言·反射
Troc_wangpeng2 小时前
R language 关于二维平面直角坐标系的制作
开发语言·机器学习
努力的家伙是不讨厌的2 小时前
解析json导出csv或者直接入库
开发语言·python·json
Envyᥫᩣ2 小时前
C#语言:从入门到精通
开发语言·c#