2-gin路由

一 基本路由

package main

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

func funcPost(c *gin.Context)  {
	c.String(http.StatusOK, "post请求")
}
func main() {
	r := gin.Default()
	r.GET("/", func(c *gin.Context) {
		c.String(http.StatusOK, "hello word")
	})
	r.POST("/",funcPost)
	//r.DELETE()
	//r.PUT()
	//r.OPTIONS()
	
	//监听端口默认为8080
	r.Run(":8000")
}

二 API参数

  • 可以通过Context的Param方法来获取API参数
  • localhost:8000/xxx/zhangsan
package main

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

func main() {
	r := gin.Default()
	r.GET("/user/:name/*action", func(c *gin.Context) {
		name := c.Param("name")
		action := c.Param("action")
		fmt.Println(action)
		//把字符串开头/截取掉
		action = strings.Trim(action, "/")
		fmt.Println(action)
		c.String(http.StatusOK, name+" is "+action)
	})
	//默认为监听8080端口
	r.Run(":8000")
}

image-20200915183717884

三 URL参数

  • URL参数可以通过DefaultQuery()或Query()方法获取
  • DefaultQuery()若参数不存在,返回默认值,Query()若不存在,返回空串
  • API http://localhost:8080/user?name=lqz
package main

import (
	"fmt"
	"net/http"

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

func main() {
	r := gin.Default()
	r.GET("/user", func(c *gin.Context) {
		//指定默认值
		//http://localhost:8080/user 才会打印出来默认的值
		//name := c.DefaultQuery("name", "世界")
		name := c.Query("name")
		c.String(http.StatusOK, fmt.Sprintf("hello %s", name))
	})
	r.Run()
}

不传递参数输出的结果:

image-20200915184112118

传递参数输出的结果:

image-20200915184144289

四 表单参数

  • 表单传输为post请求,http常见的传输格式为四种:
    • application/json
    • application/x-www-form-urlencoded
    • application/xml
    • multipart/form-data
  • 表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或from-data格式的参数
package main

import (
	"fmt"
	"net/http"

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

func main() {
	r := gin.Default()
	r.POST("/form", func(c *gin.Context) {
		username := c.PostForm("username")
		password := c.PostForm("password")
		// c.String(http.StatusOK, fmt.Sprintf("username:%s,password:%s,type:%s", username, password, types))
		c.String(http.StatusOK, fmt.Sprintf("用户名:%s,密码:%s", username, password))
	})
	r.Run()
}

image-20200915193412744

五 上传单个文件

  • multipart/form-data格式用于文件上传
  • gin文件上传与原生的net/http方法类似,不同在于gin把原生的request封装到c.Request中
package main

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

func main() {
	r := gin.Default()
	//限制上传最大尺寸
	r.MaxMultipartMemory = 8 << 20
	r.POST("/upload", func(c *gin.Context) {
		file, err := c.FormFile("file")
		if err != nil {
			c.String(500, "上传图片出错")
		}
		c.SaveUploadedFile(file, file.Filename)
		c.String(http.StatusOK, file.Filename)
	})
	r.Run()
}

image-20200915193608644

六 上传多个文件

package main

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

// gin的helloWorld

func main() {
	// 1.创建路由
	// 默认使用了2个中间件Logger(), Recovery()
	r := gin.Default()
	// 限制表单上传大小 8MB,默认为32MB
	r.MaxMultipartMemory = 8 << 20
	r.POST("/upload", func(c *gin.Context) {
		form, err := c.MultipartForm()
		if err != nil {
			c.String(http.StatusBadRequest, fmt.Sprintf("get err %s", err.Error()))
		}
		// 获取所有图片
		files := form.File["files"]
		// 遍历所有图片
		for _, file := range files {
			// 逐个存
			if err := c.SaveUploadedFile(file, file.Filename); err != nil {
				c.String(http.StatusBadRequest, fmt.Sprintf("upload err %s", err.Error()))
				return
			}
		}
		c.String(200, fmt.Sprintf("upload ok %d files", len(files)))
	})
	//默认端口号是8080
	r.Run(":8000")
}

image-20200915194131055

七 routes group

routes group是为了管理一些相同的URL

package main

import (
   "fmt"
   "github.com/gin-gonic/gin"
)

// gin的helloWorld

func main() {
   // 1.创建路由
   r := gin.Default()
   // 路由组1 ,处理GET请求
   v1 := r.Group("/v1")
   // {} 是书写规范,不写也开业
   {
      v1.GET("/login", login)
      v1.GET("submit", submit) //  /不写也可以
   } 
   v2 := r.Group("/v2")

   v2.POST("/login", login)
   v2.POST("/submit", submit)

   r.Run(":8000")
}

func login(c *gin.Context) {
   name := c.DefaultQuery("name", "lqz")
   c.String(200, fmt.Sprintf("hello %s\n", name))
}

func submit(c *gin.Context) {
   name := c.DefaultQuery("name", "egon")
   c.String(200, fmt.Sprintf("hello %s\n", name))
}

测试

get请求:127.0.0.1:8000/v1/login
get请求:127.0.0.1:8000/v1/submit

post请求:127.0.0.1:8000/v1/login
post请求:127.0.0.1:8000/v1/submit

八 路由拆分与注册

8.1 基本路由注册

适用于路由比较少的简单项目

package main

import (
   "net/http"

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

func helloHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "message": "Hello world!",
   })
}

func main() {
   r := gin.Default()
   r.GET("/hello", helloHandler)
   r.Run()
}

8.2 路由拆分成单独文件或包

当项目的规模增大后就不太适合继续在项目的main.go文件中去实现路由注册相关逻辑了,我们会倾向于把路由部分的代码都拆分出来,形成一个单独的文件或包

8.2.1 拆分到单独文件中

routers.go

package main
import (
   "net/http"

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

func helloHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "msg": "www.liuqingzheng.top",
   })
}
func testHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "status":100,
      "msg": "hello world",
   })
}

func initRouter() *gin.Engine {
   r := gin.Default()
   r.GET("/hello", helloHandler)
   r.GET("/test", testHandler)
   return r
}

main.go

package main

func main() {
   r := initRouter()
   r.Run()
}

//访问
//http://127.0.0.1:8080/test
http://127.0.0.1:8080/hello

目录结构

image-20200915230640851

8.2.2 拆分到包中

routers/routers.go需要注意此时initRouter需要改成首字母大写:

package routers
import (
   "net/http"

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

func helloHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "msg": "www.liuqingzheng.top",
   })
}
func testHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "status":100,
      "msg": "hello world",
   })
}

func InitRouter() *gin.Engine {
   r := gin.Default()
   r.GET("/hello", helloHandler)
   r.GET("/test", testHandler)
   return r
}

main.go

package main

import "gin_test/routers"

func main() {
   r := routers.InitRouter()
   r.Run()
}

目录结构

image-20200915231146634

8.3 路由拆分成多个文件

单独的一个routers文件或包已经满足不了我们的需求了

目录结构

image-20200915232150667

routers/goods.go

package routers

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

func LoadGoodsRouters(e *gin.Engine)  {
   e.GET("/good", goodHandler)
   e.GET("/goodlist", goodlistHandler)
   e.GET("/updategood", updategoodHandler)
}
func goodHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "msg": "www.liuqingzheng.top",
   })
}

func goodlistHandler(c *gin.Context) {
   c.String(http.StatusOK, "goodlistHandler")
}
func updategoodHandler(c *gin.Context) {
   c.String(http.StatusOK, "updategoodHandler")
}

routers/order.go

package routers

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

func LoadOrderRouters(e *gin.Engine)  {
   e.GET("/order", orderHandler)
   e.GET("/orderlist", orderlistHandler)
   e.GET("/updateorder", updateorderHandler)
}
func orderHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "msg": "www.liuqingzheng.top",
   })
}

func orderlistHandler(c *gin.Context) {
   c.String(http.StatusOK, "orderlistHandler")
}
func updateorderHandler(c *gin.Context) {
   c.String(http.StatusOK, "updateorderHandler")
}

routers/user.go

package routers

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

func LoadUserRouters(e *gin.Engine)  {
   e.GET("/user", userHandler)
   e.GET("/userlist", userlistHandler)
   e.GET("/updateuser", updateuserHandler)
}
func userHandler(c *gin.Context) {
   c.JSON(http.StatusOK, gin.H{
      "msg": "www.liuqingzheng.top",
   })
}

func userlistHandler(c *gin.Context) {
   c.String(http.StatusOK, "userlistHandler")
}
func updateuserHandler(c *gin.Context) {
   c.String(http.StatusOK, "updateuserHandler")
}

main.go

package main

import (
   "gin_test/routers"
   "github.com/gin-gonic/gin"
)

func main() {
   r := gin.Default()
   routers.LoadGoodsRouters(r)
   routers.LoadOrderRouters(r)
   routers.LoadUserRouters(r)
   r.Run()
}

8.4 路由拆分到不同的APP

有时候项目规模实在太大,那么我们就更倾向于把业务拆分的更详细一些,例如把不同的业务代码拆分成不同的APP。

因此我们在项目目录下单独定义一个app目录,用来存放我们不同业务线的代码文件,这样就很容易进行横向扩展。大致目录结构如下:

image-20200915233649087

app01/shop/handler.go

package shop


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

func shopHandler(c *gin.Context)  {
   c.String(http.StatusOK, "shopHandler")
}

func shopInfoHandler(c *gin.Context)  {
   c.String(http.StatusOK, "shopInfoHandler")
}

app01/shop/router.go

package shop

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

func Routers(e *gin.Engine) {
   e.GET("/shop", shopHandler)
   e.GET("/shopinfo", shopInfoHandler)
}

app01/user/handler.go

package user

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

func userHandler(c *gin.Context)  {
   c.String(http.StatusOK, "userHandler")
}

func userInfoHandler(c *gin.Context)  {
   c.String(http.StatusOK, "userInfoHandler")
}

app01/user/router.go

package user


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

func Routers(e *gin.Engine) {
   e.GET("/user", userHandler)
   e.GET("/userinfo", userInfoHandler)
}

routers/routers.go

package routers

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

type Option func(engine *gin.Engine)
var options=[]Option{}
//注册app的路由配置
func Include(opts ...Option)  {
   options=append(options,opts...)
}
//初始化
func  Init()*gin.Engine  {
   r:=gin.New()
   for _,opt:=range options{
      opt(r)
   }
   return r
}

main.go

package main

import (
   "gin_test/app01/shop"
   "gin_test/app01/user"
   "gin_test/routers"
)

func main() {
   routers.Include(shop.Routers,user.Routers)
   r:=routers.Init()
   r.Run()
}

posted @ 2021-12-01 09:06  Henry121  阅读(61)  评论(0编辑  收藏  举报