1.quick start
package main import "github.com/gin-gonic/gin" func main() { r := gin.Default() //default: router with logger and recovery(crash-free) middleware // recovery: handle "panic" r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run(":8083") // listen and serve on 0.0.0.0:8080 }
2. restful
package main import "github.com/gin-gonic/gin" func main() { // 使用默认中间件创建一个gin路由器 // logger and recovery (crash-free) 中间件 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) // 默认启动的是 8080端口,也可以自己定义启动端口 router.Run() // router.Run(":3000") for a hard coded port }
3. router.Group 路由分组
package main import ( "github.com/gin-gonic/gin" "net/http" ) func goodlist(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{ "name": "123", }) } func main() { router := gin.Default() group := router.Group("/goods") { group.GET("/list", goodlist) group.POST("/add", goodlist) } router.Run(":8083") }
4. variables in URL
package main import ( "github.com/gin-gonic/gin" "net/http" ) type Person struct { ID string `uri:"id" binding:"required,uuid"` Name string `uri:"name" binding:"required"` } func goodlist(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{ "name": ctx.Param("id"), }) } func main() { router := gin.Default() group := router.Group("/goods") { //group.GET("/list", goodlist) 不能和下面的同时出现。怎么解决? group.GET("/:id", goodlist) // *: show the path group.GET("/:id/*action", func(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{ "action": ctx.Param("action"), }) }) // add constrains to url group.GET("/:id/:name", func(c *gin.Context) { var person Person if err := c.ShouldBindUri(&person); err != nil { c.JSON(http.StatusNotFound, gin.H{"msg": err}) return } c.JSON(http.StatusOK, gin.H{"name": person.Name, "uuid": person.ID}) }) } router.Run(":8083") }
5. params from GET POST
package main import ( "github.com/gin-gonic/gin" "net/http" ) func main() { router := gin.Default() router.GET("/welcome", func(ctx *gin.Context) { fstName := ctx.DefaultQuery("name", "bobby") age := ctx.DefaultQuery("age", "12") ctx.JSON(http.StatusOK, gin.H{ "name": fstName, "age": age, }) }) router.POST("/post", func(ctx *gin.Context) { fstName := ctx.DefaultPostForm("name", "bobby") age := ctx.DefaultPostForm("age", "12") ctx.JSON(http.StatusOK, gin.H{ "name": fstName, "age": age, }) }) // url + param; body + param router.POST("/getpost", func(ctx *gin.Context) { gname := ctx.Query("gname") gage := ctx.DefaultQuery("gage", "12") fstName := ctx.PostForm("name") age := ctx.DefaultPostForm("age", "12") ctx.JSON(http.StatusOK, gin.H{ "name": fstName, "age": age, "gname": gname, "gage": gage, }) }) router.Run(":8083") }
6. output: JSON/protobuf/pure JSON
package main import ( "net/http" "github.com/gin-gonic/gin" "GoProjects/gin_start/ch05/proto" ) func main() { router := gin.Default() router.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) }) router.GET("/moreProtobuf", func(c *gin.Context) { courses := []string{"python", "django", "go"} // The specific definition of protobuf is written in the testdata/protoexample file. data := &proto.Teacher{ Name: "bobby", Course: courses, } c.ProtoBuf(http.StatusOK, data) }) router.Run(":8083") }
7. vaidator + error 注册翻译器
package main import ( "fmt" "github.com/gin-gonic/gin" "github.com/gin-gonic/gin/binding" "github.com/go-playground/locales/en" "github.com/go-playground/locales/zh" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" enTranslations "github.com/go-playground/validator/v10/translations/en" zhTranslations "github.com/go-playground/validator/v10/translations/zh" "net/http" ) // 定义一个全局翻译器T var trans ut.Translator // InitTrans 初始化翻译器 func InitTrans(locale string) (err error) { // 修改gin框架中的Validator引擎属性,实现自定制 if v, ok := binding.Validator.Engine().(*validator.Validate); ok { zhT := zh.New() // 中文翻译器 enT := en.New() // 英文翻译器 // 第一个参数是备用(fallback)的语言环境 // 后面的参数是应该支持的语言环境(支持多个) // uni := ut.New(zhT, zhT) 也是可以的 uni := ut.New(enT, zhT, enT) // locale 通常取决于 http 请求头的 'Accept-Language' var ok bool // 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找 trans, ok = uni.GetTranslator(locale) if !ok { return fmt.Errorf("uni.GetTranslator(%s) failed", locale) } // 注册翻译器 switch locale { case "en": err = enTranslations.RegisterDefaultTranslations(v, trans) case "zh": err = zhTranslations.RegisterDefaultTranslations(v, trans) default: err = enTranslations.RegisterDefaultTranslations(v, trans) } return } return } // 绑定为json type Login struct { User string `form:"user" json:"user" xml:"user" binding:"required,m=3,max=10"` Password string `form:"password" json:"password" xml:"password" binding:"required"` } type SignUpParam struct { Age uint8 `json:"age" binding:"gte=1,lte=130"` Name string `json:"name" binding:"required"` Email string `json:"email" binding:"required,email"` Password string `json:"password" binding:"required"` RePassword string `json:"re_password" binding:"required,eqfield=Password"` } func main() { if err := InitTrans("en"); err != nil { fmt.Printf("init trans failed, err:%v\n", err) return } router := gin.Default() // Example for binding JSON ({"user": "manu", "password": "123"}) router.POST("/loginJSON", func(c *gin.Context) { var json Login if err := c.ShouldBindJSON(&json); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if json.User != "manu" || json.Password != "123" { c.JSON(http.StatusUnauthorized, gin.H{"status": "unauthorized"}) return } c.JSON(http.StatusOK, gin.H{"status": "you are logged in"}) }) router.POST("/signup", func(c *gin.Context) { var u SignUpParam if err := c.ShouldBind(&u); err != nil { errs, ok := err.(validator.ValidationErrors) if !ok { // 非validator.ValidationErrors类型错误直接返回 c.JSON(http.StatusOK, gin.H{ "msg": err.Error(), }) return } // validator.ValidationErrors类型错误则进行翻译 c.JSON(http.StatusOK, gin.H{ "msg": errs.Translate(trans), }) return } // 保存入库等业务逻辑代码... c.JSON(http.StatusOK, "success") }) router.Run(":8083") }
result:
{ "msg": { "SignUpParam.Age": "Age must be 1 or greater", "SignUpParam.Email": "Email is a required field", "SignUpParam.Name": "Name is a required field", "SignUpParam.Password": "Password is a required field", "SignUpParam.RePassword": "RePassword is a required field" } }