成功最有效的方法就是向有经验的人学习!

Gin基本使用-基础介绍

Gin基本使用-基础篇

路由与传参

1、无参路由

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    //"github.com/gin-gonic/gin"
)

func main() {
    // 1、创建路由engine
    // r就是 *Engine 结构体
    r := gin.Default()
    // 2、路由绑定
    /*
        "/" 路由
        func(c *gin.Context)  处理函数
    */
    r.GET("/", func(c *gin.Context) {
        // 第一:解析get/post请求的参数
        // 第二:根据参数去查询数据库(操作数据库:添加数据、删除数据)
        // 第三:返回从数据库查询的数据
        c.String(200, "hello world")
    })
    fmt.Println("http://127.0.0.1:8000")
    // 3、启动监听端口
    // 对 net/http服务的封装,替换了 http.ListenAndServe(address, engine)
    r.Run(":8000")
}

2、API参数
可以通过Context的Param方法来获取API参数

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func GetBookDetailHandler(c *gin.Context) {
    bookId := c.Param("id")
    // gin.Context,封装了request和response 
    c.String(http.StatusOK, fmt.Sprintf("成功获取书籍详情:%s", bookId))
}
func
main() {
    // 1.创建路由 
    r := gin.Default()
    // 2.绑定路由规则,执行的函数 
    // 基本路由 /book/24/
    r.GET("/book/:id", GetBookDetailHandler)
    // 3.监听端口,默认在8080
    fmt.Println("运行地址:http://127.0.0.1:8000/book/24/")
    r.Run(":8000")
}

3、url参数
URL参数可以通过DefaultQuery()Query()方法获取
DefaultQuery()若参数不存在,返回默认值,Query()若不存在,返回空串
http://127.0.0.1:8080/user?name=zhangsan

package main

import (
    "fmt"
    "net/http"
)

import (
    "github.com/gin-gonic/gin"
)

func GetUserDetailHandler(c *gin.Context) {
    //username := c.DefaultQuery("name", "xxx") 
    username := c.Query("name")
    // gin.Context,封装了request和response
    c.String(http.StatusOK, fmt.Sprintf("姓名:%s", username))
}
func
main() {
    // 1.创建路由
    r := gin.Default()
    // 2.绑定路由规则,执行的函数 
    // 基本路由 /user?name=root
    r.GET("/user/", GetUserDetailHandler)

    // 3.监听端口,默认在8080
    fmt.Println("运行地址:http://127.0.0.1:8000/user?name=root")
    r.Run(":8000")
}

4、ShouldBind参数绑定
我们可以基于请求的 Content-Type 识别请求数据类型并利用反射机制
自动提取请求中 QueryString 、 form表单 、 JSON 、 XML 等参数到结构体中
下面的示例代码演示了 .ShouldBind() 强大的功能
它能够基于请求自动提取 JSON 、 form表单 和 QueryString 类型的数据,并把值绑定到指定的结
构体对象。

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

// Binding from JSON 
type Login struct {
    Username string `form:"username" json:"username" binding:"required"`
    Password string `form:"password" json:"password" binding:"required"`
}

func LoginHandler(c *gin.Context) {
    var login Login
    if err := c.ShouldBind(&login); err != nil {
        // 如果数据校验不通过直接返回
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
    }
    c.String(http.StatusOK, fmt.Sprintf("姓名:%s -- 密码:%s", login.Username, login.Password))
}
func
main() {
    // 1.创建路由
    r := gin.Default()
    // 2.绑定路由规则,执行的函数 
    // 基本路由 /login/
    r.POST("/login/", LoginHandler)
    // 3.监听端口,默认在8080
    fmt.Println("运行地址:http://127.0.0.1:8000/login/")
    r.Run(":8000")
}

测试

综合示例

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
)

/*
http请求两块
第一:路由
第二:处理函数
    - 获取get请求或者post请求的参数(gin第一步)
    (根据参数去查询数据库)
    - 从数据库查询并返回数据
*/

func main() {
    // 1、生成engine
    r := gin.Default()

    // 2、注册路由
    //r.GET("/hello", func(c *gin.Context) {
    //  c.String(200, "hello")
    //})
    // 2.1 无参路由
    r.GET("/hello", HelloHandler)

    // 2.2 API路由: http://127.0.0.1:8000/book/18
    // :id 使用 id来获取 18这是值
    r.GET("/book/:id", GetBookDeatilHandler)

    // 3.3 url传参: http://127.0.0.1/user?id=20&name=zhangsan
    r.GET("/user", GetUserDetailHandler)

    // 3.4 shouldBind绑定(解析post请求中复杂的json数据)
    r.POST("/login/", LoginHandler)

    r.Run(":8000")
}

// 把handler处理函数拿出来
func HelloHandler(c *gin.Context) {
    c.String(200, "hello")
}

func GetBookDeatilHandler(c *gin.Context) {
    //bookId := c.Param("id1")
    // 这里 c.Param("id") 这个id一定要和路由中 :id完全一致
    bookId := c.Param("id")
    fmt.Println(bookId, "____>")
    c.String(200, "API params")
}

func GetUserDetailHandler(c *gin.Context) {
    // 1、获取值,如果没有为 nil
    name := c.Query("name")
    // 2、获取值,如果没有使用默认值
    /*
        name : key
        default val : 如果没传入参数,就是用默认值
    */
    name2 := c.DefaultQuery("name", "default val")
    fmt.Println("获取的用户名---》", name, name2)
    c.String(200, "URL params")
}

type Login struct {
    // post请求的数据字段名一定要和 `json:"username" 一模一样
    // binding:"required" 要求username字段不能为空
    Username string `json:"username" binding:"required"`
    //Username string `json:"username"`
    Password string `json:"password"`
}

// 第四种:shouldBind方法获取json中复杂数据,并且可以对参数进行校验
func LoginHandler(c *gin.Context) {
    var login Login
    //  c.ShouldBind(&login) 方法必须要传入一个结构体对象
    // 将 net/http中的 r.Body数据解析到 Login的结构体中
    // c.ShouldBind(&login) => json.Unmarshal(bodyContent, &d)
    if err := c.ShouldBind(&login); err != nil {
        fmt.Println(err)
        c.String(200, "参数校验错误")
    }
    fmt.Println(login.Username, login.Password)
    c.String(200, "success")
}

响应返回

1、响应String

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()
    r.GET("/response/", ResponseStringHandler)
    fmt.Println("http://127.0.0.1:8000/response/")
    r.Run(":8000")
}
func ResponseStringHandler(c *gin.Context) {
    c.String(http.StatusOK, "返回简单字符串")
}

2、响应JSON

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()
    r.GET("/response/", ResponseJsonHandler)

    fmt.Println("http://127.0.0.1:8000/response/")
    r.Run(":8000")
}
func ResponseJsonHandler(c *gin.Context) {
    type Data struct {
        Msg  string `json:"msg"`
        Code int    `json:"code"`
    }
    d := Data{
        Msg:  "Json数据",
        Code: 1001,
    }
    c.JSON(http.StatusOK, d)
    //// 也可以直接使用 gin.H返回 json数据 
    // c.JSON(http.StatusOK, gin.H{ 
    // "msg": "success", 
    // }) 
}

3、路由重定向

package main

import (
    "fmt"
    "github.com/gin-gonic/gin"
    "net/http"
)

func main() {
    r := gin.Default()
    r.GET("/", func(c *gin.Context) {
        c.Redirect(http.StatusMovedPermanently, "https://gl.sh.cn")
    })
    fmt.Println("http://127.0.0.1:8000")
    r.Run(":8000")
}

路由分发

为什么需要路由分发?
我们一个项目有非常多的模块,如果全部写在一块导致代码结构混乱,不利于后续的扩展
按照大的模块,每个模块有自己独立的路由,主路由可以再main.go中进行注册
1、项目结构

2、main.go

package main

import (
    // demo_router_layer 项目根路径
    // go.mod文件中指定 module demo_router_layer
    "github.com/gin-gonic/gin"
    "xxx/routers" // 导入本地的模块
)

/*
1、初始化项目
go mod init xxx
go mod tidy    // 更新项目中使用的模块
go get         // 下载包
go.mod文件中指定 module demo_router_layer (指定导入根路径)
*/

func main() {
    // r本质 实例化 *gin.Engine结构体
    r := gin.Default() // 实例化engine引擎实例
    // 注册路由
    routers.LoadUsers(r)
    routers.LoadBooks(r)

    //utils.timeConv()
    r.Run(":8000")
}

3、routers/users.go

package routers

import "github.com/gin-gonic/gin"

// 分层注册路由
func LoadUsers(r *gin.Engine) {
    r.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
    //e.GET("/user", UserHandler)
}

func UserHandler(c *gin.Context) {
    c.String(200, "用户模块")
}

4、routers/books.go

package routers

import "github.com/gin-gonic/gin"

func LoadBooks(r *gin.Engine) {
    // 这个r就是main函数中 gin.Default() 返回的
    r.GET("/book", BookHandler)
}

func BookHandler(c *gin.Context) {
    c.String(200, "书籍模块")
}

路由分发效果

赞(1) 打赏
未经允许不得转载:陈桂林博客 » Gin基本使用-基础介绍
分享到

大佬们的评论 抢沙发

全新“一站式”建站,高质量、高售后的一条龙服务

微信 抖音 支付宝 百度 头条 快手全平台打通信息流

橙子建站.极速智能建站8折购买虚拟主机

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续给力更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫打赏

微信扫一扫打赏

登录

找回密码

注册