标签:哪些 rom lan test 接口 字符 ldb img sele
框架一直是敏捷开发中的利器,能让开发者很快的上手并做出应用。
成长总不会一蹴而就,从写出程序获取成就感,再到精通框架,快速构造应用。
Gin
是一个golang的微框架,封装比较优雅,API友好,源码注释比较明确。
具有快速灵活,容错方便等特点。
其实对于golang而言,web框架的依赖要远比Python,Java之类的要小。
自身的net/http
足够简单,性能也非常不错
。
框架更像是一些常用函数或者工具的集合。
借助框架开发,不仅可以省去很多常用的封装带来的时间,也有助于团队的编码风格和形成规范。
安装gin
go get github.com/gin-gonic/gin
gin
与hello world
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { //gin.Default方法创建路由handler router := gin.Default() //绑定路由规则和路由函数,gin支持restful方法 //gin把request和response都封装到了gin.Context的上下文环境中 router.GET("/", func(c *gin.Context) { //返回字符串 c.String(http.StatusOK, "Hello World") }) //监听端口 router.Run(":8000") }
运行代码,即可访问http://0.0.0.0:8000/寻找hello world页面
借助于postman
测试restful api
restful案例
状态码
gin代码示例
用户信息接口设计 restful风格
package main import "github.com/gin-gonic/gin" func main() { //Default返回一个默认的路由引擎 r := gin.Default() //匿名函数可以用有名函数,也可以匿名函数 r.GET("/user/info", func(c *gin.Context) { //输出json结果给调用方 c.JSON(200, gin.H{ "message": "get user info succ", }) }) r.POST("/user/info", func(c *gin.Context) { //输出json结果给调用方 c.JSON(200, gin.H{ "message": "create user info succ", }) }) r.PUT("/user/info", func(c *gin.Context) { //输出json结果给调用方 c.JSON(200, gin.H{ "message": "update user info succ", }) }) r.DELETE("/user/info", func(c *gin.Context) { //输出json结果给调用方 c.JSON(200, gin.H{ "message": "delete user info succ ", }) }) r.Run() // listen and serve on 0.0.0.0:8080 }
非restful风格的API
/user/info /user/create /user/delete /user/update
实例代码,传入2个get参数
querystring传递参数
package main import "github.com/gin-gonic/gin" func main() { //Default返回一个默认的路由引擎 r := gin.Default() r.GET("/user/search", func(c *gin.Context) { //username := c.DefaultQuery("username", "少林") username := c.Query("username") address := c.Query("address") //输出json结果给调用方 c.JSON(200, gin.H{ "message": "pong", "username": username, "address": address, }) }) r.Run() // listen and serve on 0.0.0.0:8080 }
通过postman
发送请求,携带参数
127.0.0.1:8080/user/search?username=超哥&address=沙河
DefaultQuery返回URL参数
package main import "github.com/gin-gonic/gin" func main() { //Default返回一个默认的路由引擎 r := gin.Default() r.GET("/user/search", func(c *gin.Context) { //使用默认值参数 username := c.DefaultQuery("username", "超老板") //username := c.Query("username") address := c.Query("address") //输出json结果给调用方 c.JSON(200, gin.H{ "message": "pong", "username": username, "address": address, }) }) r.Run() // listen and serve on 0.0.0.0:8080 }
访问结果
127.0.0.1:8080/user/search?address=沙河
不建议使用,使用表单或者querystring方式获取参数
package main import "github.com/gin-gonic/gin" func main() { //Default返回一个默认的路由引擎 r := gin.Default() r.GET("/user/search/:username/:address", func(c *gin.Context) { username := c.Param("username") address := c.Param("address") //输出json结果给调用方 c.JSON(200, gin.H{ "message": "pong", "username": username, "address": address, }) }) r.Run(":8080") // listen and serve on 0.0.0.0:8080 }
访问方式
127.0.0.1:8080/user/search/chao/beijing/
package main import "github.com/gin-gonic/gin" func main() { //Default返回一个默认的路由引擎 r := gin.Default() r.POST("/user/search", func(c *gin.Context) { //username := c.DefaultPostForm("username", "少林") username := c.PostForm("username") address := c.PostForm("address") //输出json结果给调用方 c.JSON(200, gin.H{ "message": "pong", "username": username, "address": address, }) }) r.Run(":8080") // listen and serve on 0.0.0.0:8080 }
运行方式,使用post方式提交form
上传文件的名字应该由服务端统一文件名
规则,防止非法字符
package main import ( "fmt" "log" "net/http" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() // Set a lower memory limit for multipart forms (default is 32 MiB) // router.MaxMultipartMemory = 8 << 20 // 8 MiB router.POST("/upload", func(c *gin.Context) { // single file file, err := c.FormFile("file") if err != nil { c.JSON(http.StatusInternalServerError, gin.H{ "message": err.Error(), }) return } // log.Println(file.Filename) dst := fmt.Sprintf("文件夹路径/%s", file.Filename) // Upload the file to specific dst. c.SaveUploadedFile(file, dst) c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("‘%s‘ uploaded!", file.Filename), }) }) router.Run(":8080") }
上传单个文件
上传多个文件
package main import ( "fmt" "log" "net/http" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() //文件比较大,默认文件存在内中占32M,大于32M就写入到磁盘 // Set a lower memory limit for multipart forms (default is 32 MiB) //设置上传文件的内存大小 // router.MaxMultipartMemory = 8 << 20 // 8 MiB router.POST("/upload", func(c *gin.Context) { // Multipart form form, _ := c.MultipartForm() files := form.File["file"] for index, file := range files { log.Println(file.Filename) dst := fmt.Sprintf("/Users/yuchao/go/src/gostudy/gobook/%s_%d", file.Filename, index) // Upload the file to specific dst. c.SaveUploadedFile(file, dst) } c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("%d files uploaded!", len(files)), }) }) router.Run(":8080") }
上传方式
把前缀一样的url,放入一个组
package main import "github.com/gin-gonic/gin" func login(ctx *gin.Context) { ctx.JSON(200, gin.H{ "message": "success", }) } func read(ctx *gin.Context) { ctx.JSON(200, gin.H{ "message": "success", }) } func submit(ctx *gin.Context) { ctx.JSON(200, gin.H{ "message": "success", }) } func main() { //Default返回一个默认的路由引擎 router := gin.Default() // Simple group: v1 // /v1/login // /v1/submit // /v1/read v1 := router.Group("/v1") { v1.POST("/login", login) v1.POST("/submit", submit) v1.POST("/read", read) } // Simple group: v2 // /v2/login // /v2/submit // /v2/read v2 := router.Group("/v2") { v2.POST("/login", login) v2.POST("/submit", submit) v2.POST("/read", read) } router.Run(":8080") }
运行方式
使用方便,提高开发效率
通过反射机制,自动提取querystring,from表单,json,xml等参数到struct中
通过http协议中的context type,识别json、xml或是表单
package main import ( "fmt" "net/http" "github.com/gin-gonic/gin" ) // Binding from JSON type 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 login Login if err := c.ShouldBindJSON(&login); err == nil { fmt.Printf("login info:%#v\n", login) c.JSON(http.StatusOK, gin.H{ "user": login.User, "password": login.Password, }) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }) // Example for binding a HTML form (user=manu&password=123) router.POST("/loginForm", func(c *gin.Context) { var login Login // This will infer what binder to use depending on the content-type header. if err := c.ShouldBind(&login); err == nil { c.JSON(http.StatusOK, gin.H{ "user": login.User, "password": login.Password, }) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }) // Example for binding a HTML querystring (user=manu&password=123) router.GET("/loginForm", func(c *gin.Context) { var login Login // This will infer what binder to use depending on the content-type header. if err := c.ShouldBind(&login); err == nil { c.JSON(http.StatusOK, gin.H{ "user": login.User, "password": login.Password, }) } else { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) } }) // Listen and serve on 0.0.0.0:8080 router.Run(":8080") }
json方式提交数据
form方式提交
json渲染
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() // gin.H is a shortcut for map[string]interface{} r.GET("/someJSON", func(c *gin.Context) { //第一种方式,自己拼json c.JSON(http.StatusOK, gin.H{"message": "你大爷", "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 = "大王" msg.Message = "大王,唐僧给你捉来了" msg.Number = 123 // Note that msg.Name becomes "user" in the JSON c.JSON(http.StatusOK, msg) }) // Listen and serve on 0.0.0.0:8080 r.Run(":8080") }
xml渲染
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { r := gin.Default() r.GET("/moreXML", func(c *gin.Context) { // You also can use a struct type MessageRecord struct { Name string Message string Number int } var msg MessageRecord msg.Name = "二王" msg.Message = "你大爷" msg.Number = 123 c.XML(http.StatusOK, msg) }) // Listen and serve on 0.0.0.0:8080 r.Run(":8080") }
HTML 模板渲染
package main import ( "net/http" "github.com/gin-gonic/gin" ) func main() { router := gin.Default() //模板路径,一层就是templates/* //两层就是templates/**/* router.LoadHTMLGlob("templates/**/*") router.GET("/posts/index", func(c *gin.Context) { c.HTML(http.StatusOK, "posts/index.tmpl", gin.H{ "title": "我是标题", }) }) router.GET("/users/index", func(c *gin.Context) { c.HTML(http.StatusOK, "users/index.tmpl", gin.H{ "title": "我是标题", }) }) router.Run(":8080") }
访问路径
注意先go build main.go 再运行
http://127.0.0.1:8080/users/index
http://127.0.0.1:8080/posts/index
package main import ( "github.com/gin-gonic/gin" ) func main() { r := gin.Default() //在main.go同级准备static文件夹,内含图片 r.Static("/static", "./static") // Listen and serve on 0.0.0.0:8080 r.Run(":8080") }
注意先go build main.go 再运行
go build main.go ./main.go http://127.0.0.1:8080/static/1.png
golang的net/http设计的一大特点就是特别容易构建中间件。
gin也提供了类似的中间件。需要注意的是中间件只对注册过的路由函数起作用。
对于分组路由,嵌套使用中间件,可以限定中间件的作用范围。
中间件分为全局中间件,单个路由中间件和群组中间件。
Gin框架允许请求处理过程中,加入用户自己的钩子函数。这个函数就是中间件 利用中间件可以处理例如耗时统计,日志打印,登录校验等
计算耗时的中间件
package main import ( "log" "time" "net/http" "github.com/gin-gonic/gin" ) func StatCost() gin.HandlerFunc { return func(c *gin.Context) { t := time.Now() //可以设置一些公共参数, c.Set("example", "12345") //等其他中间件先执行 c.Next() //获取耗时 latency := time.Since(t) //打印花费的时间 319微秒 log.Printf("total cost time:%d us", latency/1000) } } func main() { //新建一个路由 gin.New(),没有中间件 // gin.Default()最常用,包含了中间件 //r := gin.New() r := gin.Default() //Use是全局中间件,传入一个 r.Use(StatCost()) r.GET("/test", func(c *gin.Context) { example := c.MustGet("example").(string) // it would print: "12345" log.Println(example) // c.JSON(http.StatusOK, gin.H{ "message": "success", }) }) // Listen and serve on 0.0.0.0:8080 r.Run(":8080") }
gin路由部分用的是
https://github.com/julienschmidt/httprouter
package main import "github.com/gin-gonic/gin" func index(ctx *gin.Context) { ctx.JSON(200, gin.H{ "message": "index", }) } func main() { //Defatult返回一个默认的路由引擎 router := gin.Default() router.POST("/", index) router.POST("/search", index) router.POST("/support", index) router.POST("/blog/:post", index) router.POST("/about", index) router.POST("/contact", index) router.POST(":8080", index) }
共用url前缀
标签:哪些 rom lan test 接口 字符 ldb img sele
原文地址:https://www.cnblogs.com/open-yang/p/11256952.html