package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/json", func(c *gin.Context) {
// 方法:使用map序列化json数据
data := map[string]interface{}{
"name": "dahe",
"message": "json method",
"age": 18,
}
// 返回状态码和json数据
c.JSON(http.StatusOK, data)
})
r.Run(":9090") // 启动server
}
更简单的方法:使用gin.H
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/json", func(c *gin.Context) {
// 方法:使用gin.H
data := gin.H{
"name": "wangwei",
"age": 18,
}
// 返回状态码和json数据
c.JSON(http.StatusOK, data)
})
r.Run(":9090") // 启动server
}
Gin很灵活,我们还可以使用结构体:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
type msg struct {
Name string
Message string
Age int
}
r.GET("/json", func(c *gin.Context) {
// 方法:使用结构体
data := msg{
"dahe",
"你好世界!",
22,
}
// 返回状态码和json数据
c.JSON(http.StatusOK, data)
})
r.Run(":9090") // 启动server
}
附:灵活使用tag来自定义json数据属性名:
type msg struct {
Name string `json:"name"`
Message string
Age int
}
querystring
指的是URL中?
后面携带的参数,例如:/user/search?username=文杰&address=china
。 获取请求的querystring
参数的方法如下:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/query", func(c *gin.Context) {
// 获取浏览器的发出请求携带的 query string 参数
name := c.Query("name")
c.JSON(http.StatusOK, gin.H{
"name": name,
})
})
r.Run(":9090") // 启动server
}
访问:http://127.0.0.1:9090/query?name=dahe
输出:{“name”:“dahe”}
设置没有接受搜索内容的默认参数值:
name := c.DefaultQuery("name", "无名氏")
// 如果没有传入参数,默认接受值:无名氏
访问:http://127.0.0.1:9090/query
输出:{“name”:“无名氏”}
带bool值的接受:
name, ok := c.GetQuery("name")
if !ok {
// 没有传值,则设置默认的值
name = "无名氏"
}
接受多个值的情况:
r.GET("/query", func(c *gin.Context) {
// 获取浏览器的发出请求携带的 query string 参数
name := c.Query("name")
age := c.Query("age")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
访问:http://127.0.0.1:9090/query?name=dahe&age=18
输出:{“age”:“18”,“name”:“dahe”}
login.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>login</title>
</head>
<body>
<form action="/login/" method="post">
账号:
<input type="text" name="username" id="username">
密码:
<input type="password" name="password" id="password">
<input type="submit" value="登录">
</form>
</body>
</html>
后端接受接口:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.LoadHTMLFiles("./login.html")
// 登录模块
r.GET("/login", func(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", nil)
})
// 接受form表单数据
r.POST("/login", func(c *gin.Context) {
// 获取form表单数据
username := c.PostForm("username")
password := c.PostForm("password")
c.JSON(http.StatusOK, gin.H{
"Name": username,
"Password": password,
})
})
r.Run(":9090") // 启动server
}
也可以使用DefaultPostForm
来接受值:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.LoadHTMLFiles("./login.html")
// 登录模块
r.GET("/login", func(c *gin.Context) {
c.HTML(http.StatusOK, "login.html", nil)
})
// 接受form表单数据
r.POST("/login", func(c *gin.Context) {
// 获取form表单数据
username := c.DefaultPostForm("username", "李华")
password := c.DefaultPostForm("password", "admin")
msg := c.DefaultPostForm("msg", "晚上好!")
c.JSON(http.StatusOK, gin.H{
"Name": username,
"Password": password,
"msg": msg,
})
})
r.Run(":9090") // 启动server
}
由于form表单没有msg字段,所以msg采用默认的值
输出:{"Name":"admin","Password":"111111","msg":"晚上好!"}
请求的参数通过URL路径传递,例如:/user/search/dahe/用户1359
。 获取请求URL路径中的参数的方式如下:
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/:name/:age", func(c *gin.Context) {
name := c.Param("name")
age := c.Param("age")
c.JSON(http.StatusOK, gin.H{
"name": name,
"age": age,
})
})
r.Run(":9090") // 启动server
}
访问路径:http://localhost:9090/dahe/18
输出:{“age”:“18”,“name”:“dahe”}
当前端请求的数据通过JSON提交时,例如向/json
发送一个POST请求,则获取请求参数的方式如下:
r.POST("/json", func(c *gin.Context) {
// 注意:下面为了举例子方便,暂时忽略了错误处理
b, _ := c.GetRawData() // 从c.Request.Body读取请求数据
// 定义map或结构体
var m map[string]interface{}
// 反序列化
_ = json.Unmarshal(b, &m)
c.JSON(http.StatusOK, m)
})
为了能够更方便的获取请求相关参数,提高开发效率,我们可以基于请求的Content-Type
识别请求数据类型并利用反射机制自动提取请求中QueryString
、form表单
、JSON
、XML
等参数到结构体中
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
// 用户结构体
type UserInfo struct {
username string
password string
}
func main() {
r := gin.Default()
r.GET("/", func(c *gin.Context) {
username := c.Query("username")
password := c.Query("password")
u := UserInfo{
username: username,
password: password,
}
fmt.Printf("%#v\n", u)
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
})
r.Run(":9090") // 启动server
}
访问:http://localhost:9090/?username=dahe&password=123
控制台输出:main.UserInfo{username:“dahe”, password:“123”}
.ShouldBind()
强大的功能,它能够基于请求自动提取JSON
、form表单
和QueryString
类型的数据,并把值绑定到指定的结构体对象
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
// 用户结构体
type UserInfo struct {
Username string `form:"username" json:"username"`
Password string `form:"password" json:"password"`
}
func main() {
r := gin.Default()
r.GET("/user", func(c *gin.Context) {
var u UserInfo // 声明一个UserInfo类型的变量u
err := c.ShouldBind(&u)
if err != nil {
c.JSON(http.StatusBadRequest, gin.H{
"error": err.Error(),
})
} else {
fmt.Printf("%#v\n", u)
c.JSON(http.StatusOK, gin.H{
"message": "ok",
})
}
})
r.Run(":9090") // 启动server
}
访问:http://localhost:9090/user?username=dahe&password=admin
控制台输出:main.UserInfo{Username:“dahe”, Password:“admin”}
ShouldBind
会按照下面的顺序解析请求中的数据完成绑定:
Form
绑定引擎(query)。content-type
是否为 JSON
或 XML
,然后再使用 Form(form-data)。更完善的实例:
// 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()
// 绑定JSON的示例 ({"user": "q1mi", "password": "123456"})
router.POST("/loginJSON", func(c *gin.Context) {
var login Login
if err := c.ShouldBind(&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()})
}
})
// 绑定form表单示例 (user=q1mi&password=123456)
router.POST("/loginForm", func(c *gin.Context) {
var login Login
// ShouldBind()会根据请求的Content-Type自行选择绑定器
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()})
}
})
// 绑定QueryString示例 (/loginQuery?user=q1mi&password=123456)
router.GET("/loginForm", func(c *gin.Context) {
var login Login
// ShouldBind()会根据请求的Content-Type自行选择绑定器
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")
}