介绍
- Gin是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确,具有快速灵活,容错方便等特点
- 对于golang而言,web框架的依赖要远比Python,Java之类的要小。自身的net/http足够简单,性能也非常不错
- 借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范
安装
```go 1.安装Gin go get -u github.com/gin-gonic/gin 2.引入包 import “github.com/gin-gonic/gin” 3.(可选)导入net/http。例如,如果使用常量,则需要这样做http.StatusOK。 import “net/http”
//示例 package main import (“github.com/gin-gonic/gin”) func main(){ //创建路由 r:=gin.Default() r.GET(“/“,func(c *gin.Context){ c.String(http.StatusOK,”hello world”) }) } //监听端口 //如果不指定端口则默认为8080 c.run(“:80”)
<a name="29667296"></a>#### 基本路由> gin框架中采用的路由库是基于httprouter做的> ```gopackage mainimport("net/http""github.com/gin-gonic/gin")func main(){r:=gin.Default()r.GET("/",func(c *gin.Context){c.String(http.StatusOK,"hello word")})r.POST("/delUser",DelUser)//监听80端口r.run(":8000")}
API参数
可以通过Context的Param方法来获取API参数
package mainimport("net/http""strings""github.com/gin-gonic/gin")func main(){r:=gin.Default()r.GET("/user/:name/*action",func(c *gin.Context){name:=c.Param("name")action:=c.Param("acion")//截取action=strings.Trim(action,"/")c.String(http.StatusOK,name+"is"+action)})//默认监听8080端口c.Run(":8080")}
URL参数
URL参数可以通过
DefaultQuery()或Query()方法获取DefaultQuery()若参数不存在,则返回默认值,Query()若不存在则返回空字符串
package mainimport ("net/http""github.com/gin-gonic/gin")func main(){r:=gin.Default()r.GET("/user",func(c *gin.Context){name:= c.DefaultQuery("name","Nice")c.String(http.StatusOK,fmt.Sprintf("%s",name))})c.Run(":8000")}
表单参数
表单传输为post请求,http常见的传输格式为四种
- application/json
- application/x-www-form-urlencoded
- application/xml
- multipart/form-data
表单参数可以通过PostForm()方法获取,该方法默认解析的是x-www-form-urlencoded或form-data格式的参数
package mainimport("fmt""net/http""github.com/gin-gonic/gin")func main(){r:=gin.Default()r.POST("form",func(c *gin.Context){types:=c.DefaultPostForm("type","post")username:=c.PostForm("userName")password:=c.PostForm("pwd")c.String(http.StatusOk,fmt.Sprintf("%v",username)})c.Run(":8000")}
单个文件
multipart/form-data格式用于文件上传
gin文件上传与原生的net/http方法类似,不同于在gin把原生的request封装到c.Request中
package mainimport ("github.com/gin-gonic/gin")func main(){r:=gin.Default()//限制上传最大尺寸r.MaxMultipartMemory=8<<20r.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)}})c.Run(":800")}
上传多个文件
```go import ( “fmt” “github.com/gin-gonic/gin” “net/http” )
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”) }
<a name="84bf9a07"></a>#### routees group> routes group 是为了管理一些相同的URL> ```gopackage mainimport ("github.com/gin-gonic/gin""net/http""fmt")func main(){r:=gin.Default()}
路由的拆分与注册
- 基本的路由注册 适用于路由条目较少的简单下面或者项目demo
```go package main
import ( “net/http”
"github.com/gin-gonic/gin"
)
func helloHandler(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ “message”: “Hello www.topgoer.com!”, }) }
func main() { r := gin.Default() r.GET(“/topgoer”, helloHandler) if err := r.Run(); err != nil { fmt.Println(“startup service failed, err:%v\n”, err) } }
> 2. 路由拆分成单独的文件或包> 当项目的规模增大后就不太适合继续在项目的main.go文件中去实现注册的相关逻辑,所以更加偏向于抽出路由模块的代码出来,形成单独一个文件> ```gopackage routerimport "github.com/gin-gonic/gin"import ("net/http")func helloHandler(c *gin.Context) {c.JSON(http.StatusOK, gin.H{"message": "Hello www.topgoer.com",})}// SetupRouter 配置路由信息func SetupRouter() *gin.Engine {r := gin.Default()r.GET("/topgoer", helloHandler)return r}package mainimport ("fmt""router_example/router")func main() {r := router.SetupRouter()if err := r.Run(); err != nil {fmt.Println("err failed", err)}}
当前目录结构如下
router_example├── go.mod├── main.go└── router└── routers.go
路由拆分成多个文件
当业务规模继续膨胀,单独的一个routers文件或包已经满足不了需求,所以可以分开定义多个路由文件
```go package router
import “github.com/gin-gonic/gin”
func LoadSystem(e *gin.Engine) { r := gin.Default() { r.GET(“findSystemId”, findSystemId) r.GET(“findAll”,findAll) } } package router
import “github.com/gin-gonic/gin”
func LoadUser(e *gin.Engine) { r := gin.Default() { r.GET(“findByUserId”, findByUserId) r.GET(“findAllUser”, findAllUser) } }
main.go func main() { r := gin.Default() //加载系统路由 router.LoadSystem(r) //加载用户路由 router.LoadUser(r) if err := r.Run(); err != nil { fmt.Println(err) } }
> 当前目录结构如下> ```gorouter_example├── go.mod├── main.go└── router└── user.go└── system.go
路由拆分到不同的APP
项目规模太大,那么更倾向于把业务拆分的更详细一些,例如把不同的业务代码拆分成不同的APP
router_example├──app| ├──user| | ├──handle.go| | ├──router.go| ├──system| | ├──handle.go| | ├──router.go├── go.mod├── main.go└── router└── routers.go```go system package system
import ( “github.com/gin-gonic/gin” “net/http” )
func findBySystemId(c *gin.Context) { c.JSON(http.StatusOK, gin.H{ “message”: “findBySystemId”, }) } package system
import “github.com/gin-gonic/gin”
func Routers(e gin.Engine) { e.GET(“findBySystemId”, findBySystemId) } user package user import ( “github.com/gin-gonic/gin” “net/http” ) func findByUserId(c gin.Context) { c.JSON(http.StatusOK, gin.H{ “message”: “findByUserId”, }) } package user
import ( “github.com/gin-gonic/gin” )
func Routers(e *gin.Engine) { e.GET(“findByUserId”, findByUserId) }
package main
import ( “fmt” “router_example/router” “router_example/service/system” “router_example/service/user” )
func main() { //加载多个路由 router.Include(user.Routers, system.Routers) //初始化 r := router.Init() if err := r.Run(); err != nil { fmt.Println(err) } } ```

