少啰嗦,直接上Gin代码:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "hello world")
})
r.Run(":8000")
}
说明:使用Gin框架生成了一个本地可以访问的路由http://127.0.0.1:8000/
,页面显示 hello world
。
看看源代码,gin.Default()
func Default() *Engine {
debugPrintWARNINGDefault()
engine := New()
engine.Use(Logger(), Recovery())
return engine
}
说明:使用了默认的配置,默认配置两个中间件Logger(), Recovery()
获取参数:
r.GET("/user/:name", func(c *gin.Context) {
name := c.Param("name")
c.String(http.StatusOK, name)
})
说明:在本地访问http://127.0.0.1:8000/user/ququ
,就可以网页上显示ququ这个路由变量。
r.GET("/user/:name/*action", func(c *gin.Context) {
name := c.Param("name")
action := c.Param("action")
c.String(http.StatusOK, name + " is " + action)
})
说明: *
号截取路由后面的内容。http://127.0.0.1:8000/user/ququ/aaa/bbb
访问后,页面输出 ququ is /aaa/bbb
问好传参
.GET("/user", func(c *gin.Context) {
name := c.DefaultQuery("name", "Jack")
c.String(http.StatusOK, fmt.Sprintf("Hello %s", name))
})
说明:当访问http://127.0.0.1:8000/user
时,得到Hello Jack
,当访问http://127.0.0.1:8000/user?name=Allen
时,得到Hello Allen
。
post表单参数 form-data
type1 := c.DefaultPostForm("type", "alert")
username := c.PostForm("username")
password := c.PostForm("password")
hobbys := c.PostFormArray("hobby")
c.String(http.StatusOK, fmt.Sprintf("type is %s, username is %s, password is %s, hobby is %v",
type1, username, password, hobbys))
说明:返回type is alert, username is ququ, password is 123, hobby is [movie ping-pong]
表单上传文件
r.POST("/upload", func(c *gin.Context) {
file, _ := c.FormFile("file")
log.Println(file.Filename)
c.SaveUploadedFile(file, file.Filename)
c.String(http.StatusOK, fmt.Sprintf("%s upload!", file.Filename))
})
表单上传多个文件
// 限制文件上传大小位8M
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("get err %s", err.Error()))
return
}
}
c.String(200, fmt.Sprintf("upload ok %d fiels", len(files)))
})
实现路由分组
v1 := r.Group("/v1")
{
v1.GET("/login", login)
v1.GET("/submit", submit)
}
v2 := r.Group("v2")
{
v2.POST("/login", login)
v2.POST("/submit", submit)
}
gin数据解析和绑定
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Login struct {
User string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
Password string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("loginJSON", func(c *gin.Context) {
var json Login
if err := c.ShouldBindJSON(&json); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"err": err.Error()})
return
}
if json.User != "root" || json.Password != "admin" {
c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
r.Run(":8000")
}
另外一种:
func main() {
r := gin.Default()
r.POST("loginJSON", func(c *gin.Context) {
var form Login
// 根据请求头中的content-type自动推断
if err := c.Bind(&form); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
}
if form.User != "root" || form.Password != "admin" {
c.JSON(http.StatusBadRequest, gin.H{"status": "304"})
return
}
c.JSON(http.StatusOK, gin.H{"status": "200"})
})
r.Run(":8000")
}
gin的各种响应
// 1 json
r.GET("/someJSON", func(c *gin.Context) {
c.JSON(200, gin.H{"message": "someJSON", "status": 200})
})
// 2 结构体响应
r.GET("someStruct", func(c *gin.Context) {
var msg struct{
Name string
Message string
Number int
}
msg.Name = "root"
msg.Message = "message"
msg.Number = 123
c.JSON(200, msg)
})
// 3 XML
r.GET("/someXML", func(c *gin.Context) {
c.XML(200, gin.H{"message": "abc"})
})
// 4 YAML
r.GET("/someYAML", func(c *gin.Context) {
c.YAML(200, gin.H{"name": "zhangsan"})
})
// 5 Protobuf
r.GET("/someProtoBuf", func(c *gin.Context) {
reps := []int64{int64(1), int64(2)}
lable := "lable"
data := &protoexample.Test{
Label:&lable,
Reps:reps,
}
c.ProtoBuf(200, data)
})
或者渲染HTML模板
func main() {
r := gin.Default()
r.LoadHTMLGlob("templates/*")
r.GET("/index", func(c *gin.Context) {
c.HTML(200, "index.templ", gin.H{"title": "我的标题"})
})
r.Run(":8000")
}
在本地同级目录下,新建templates/index.templ文件
<html>
<h1>
{{.title}}
</h1>
</html>
重定向
r.GET("/redirect", func(c *gin.Context) {
c.Redirect(http.StatusMovedPermanently, "http://www.baidu.com")
})
中间件
func MiddleWare() gin.HandlerFunc {
return func(c *gin.Context) {
t := time.Now()
fmt.Println("MiddleWare: 中间件执行开始")
c.Set("request", "中间件")
c.Next()
status := c.Writer.Status()
fmt.Println("MiddleWare: 中间件执行完毕", status)
t2 := time.Since(t)
fmt.Println("time:", t2)
}
}
func main() {
r := gin.Default()
r.Use(MiddleWare())
{
r.GET("/middleware", func(c *gin.Context) {
req, _ := c.Get("request")
fmt.Println("request:", req)
c.JSON(200, gin.H{"request": req})
})
}
r.Run(":8000")
}