当前位置:网站首页>Gin 入门实战
Gin 入门实战
2022-07-06 18:01:00 【hualaoshuan】
本篇概要:
1. 环境搭建、热加载;
# 下载 gin
cd ~/go/go-gin2
go get -u github.com/gin-gonic/gin
# 如果无法下载,尝试
go env -w GO111MODULE=on
go env -w GOPROXY=https://mirrors.aliyun.com/goproxy/,direct
# 项目准备(使用 go.mod 管理项目)
cd ~/go/go-gin2/gindemo01
go mod init gindemo01
# 代码写完后编译
go run main.go
# 第三方热加载
# 文档:https://github.com/gravityblast/fresh
export GOPROXY=https://goproxy.io
go get -u github.com/pilu/fresh
# fresh 放入项目文件夹,会在当前目录生成 tmp 目录:
fresh
- 文件
~/go/go-gin2/gindemo01/main.go
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, "值:%v", "你好")
})
// 创建 web 服务,默认 8080 端口
r.Run(":8001")
}
2. 响应数据;
- 文件
~/go/go-gin2/gindemo01/templates/index.html
<h1>{
{.title}}</h1>
- 文件
~/go/go-gin2/gindemo01/main.go
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
type Article struct {
Title string `json:"title"`
Desc string `json:"desc"`
Content string `json:"content"`
}
func main() {
// 创建默认路由引擎
r := gin.Default()
// 配置模板路径
r.LoadHTMLGlob("templates/*")
// 配置路由
r.GET("/", func(c *gin.Context) {
// 返回字符串
c.String(http.StatusOK, "值:%v", "首页")
// 返回json
c.JSON(http.StatusOK, map[string]interface{
}{
"success" : true,
"msg": "完成",
})
// 内置方法返回 json
c.JSON(http.StatusOK, gin.H{
"success" : true,
"msg": "完成2",
})
// 实例化结构体数据
a := &Article{
"标题",
"介绍",
"内容",
}
c.JSON(http.StatusOK, a)
// {"title":"标题","desc":"介绍","content":"内容"}
// 返回jsonp
// http://localhost:8001/?callback=12
c.JSONP(http.StatusOK, a)
// 返回 xml
c.XML(http.StatusOK, gin.H{
"success" : false,
"msg": "xml",
})
// 渲染 html
c.HTML(http.StatusOK, "index.html", gin.H{
"title" : "首页1",
})
})
// 创建 web 服务,默认 8080 端口
r.Run(":8001")
}
3. 路由传值;
- 文件
~/go/go-gin2/gindemo01/main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"net/http"
)
type UserInfo struct {
Username string `json:"username" form:"username"`
Passwd string `json:"passwd" form:"passwd"`
Age string `json:"age" form:"age"`
}
func main() {
// 创建默认路由引擎
r := gin.Default()
// 获取 get 传值
r.GET("/user", func(c *gin.Context) {
username := c.Query("username")
page := c.DefaultQuery("page","1")
// http://localhost:8001/user?username=hua
c.JSON(http.StatusOK, gin.H{
"username" : username,
"page": page,
})
})
// 获取"表单"的 post 传值
r.POST("/addUser", func(c *gin.Context) {
username := c.PostForm("username")
passwd := c.PostForm("passwd")
age := c.DefaultPostForm("age", "20")
c.JSON(http.StatusOK, gin.H{
"username" : username,
"passwd": passwd,
"age": age,
})
})
//绑定到结构体
// http://localhost:8001/getUser?username=hua&passwd=123456
r.GET("/getUser", func(c *gin.Context) {
user := &UserInfo{
}
if err := c.ShouldBind(&user); err==nil {
fmt.Printf("%#v", user) // 打印
c.JSON(http.StatusOK, user)
} else {
c.JSON(http.StatusOK, gin.H{
"err": err.Error(),
})
}
})
r.POST("/addUser2", func(c *gin.Context) {
user := &UserInfo{
}
if err := c.ShouldBind(&user); err==nil {
fmt.Printf("%#v", user) // 打印
c.JSON(http.StatusOK, user)
} else {
c.JSON(http.StatusOK, gin.H{
"err": err.Error(),
})
}
})
// 动态路由
r.GET("/list/:cid", func(c *gin.Context) {
cid := c.Param("cid")
c.String(http.StatusOK, "%v", cid)
})
// 创建 web 服务,默认 8080 端口
r.Run(":8001")
}
4. 路由分组:
- 文件
~/go/go-gin2/gindemo01/routers/defaultRouters.go
package routers
import (
"github.com/gin-gonic/gin"
"net/http"
)
func DefaultRoutersInit (r *gin.Engine) {
defaultRouters := r.Group("/")
{
defaultRouters.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "首页")
})
}
}
- 文件
~/go/go-gin2/gindemo01/main.go
package main
import (
"gindemo01/routers"
"github.com/gin-gonic/gin"
)
func main() {
// 创建默认路由引擎
var r = gin.Default()
//路由分组
routers.DefaultRoutersInit(r)
// 创建 web 服务,默认 8080 端口
r.Run(":8001")
}
5. 自定义控制器、控制器的继承;
- 文件
~/go/go-gin2/gindemo01/controllers/baseControllers.go
package _default
import (
"github.com/gin-gonic/gin"
"net/http"
)
type BaseController struct {
}
func (con BaseController) success (c *gin.Context) {
c.String(http.StatusOK, "ok")
}
func (con BaseController) error (c *gin.Context) {
c.String(http.StatusOK, "error")
}
- 文件
~/go/go-gin2/gindemo01/controllers/userControllers.go
package _default
import (
"github.com/gin-gonic/gin"
"net/http"
)
type UserController struct{
BaseController // 控制器继承
}
func (con UserController) Index (c *gin.Context) {
c.String(http.StatusOK, "用户列表")
}
func (con UserController) Add (c *gin.Context) {
c.String(http.StatusOK, "添加用户")
con.success(c)
}
- 文件
~/go/go-gin2/gindemo01/routers/defaultRouters.go
package routers
import (
_default "gindemo01/controllers/default"
"github.com/gin-gonic/gin"
"net/http"
)
func DefaultRoutersInit (r *gin.Engine) {
defaultRouters := r.Group("/")
{
defaultRouters.GET("/", func(c *gin.Context) {
c.String(http.StatusOK, "首页")
})
// 用户列表
// UserIndex() 执行方法,不加括号是注册方法
defaultRouters.GET("/user", _default.UserController{
}.Index)
// 添加用户
defaultRouters.GET("/user/add", _default.UserController{
}.Add)
}
}
6. 路由中间件;
如果在中间件中使用了 goroutine:
当在中间件或者 handler 中启动新的 goroutine 时,不能使用原始的上下文
c *gin.Context
,必须使用其只读副本c.Copy()
文件
~/go/go-gin2/gindemo01/middlewares/init.go
package middlewares
import (
"fmt"
"github.com/gin-gonic/gin"
"time"
)
func InitMiddleware(c *gin.Context) {
fmt.Println(time.Now())
fmt.Println(c.Request.URL)
// 设置数据
c.Set("username", "zhang")
// 定义协程统计日志
cc := c.Copy()
go func() {
time.Sleep(2 * time.Second)
fmt.Println("Done! in path " + cc.Request.URL.Path)
}()
}
- 文件
~/go/go-gin2/gindemo01/routers/defaultRouters.go
package routers
import (
"fmt"
_default "gindemo01/controllers/default"
"gindemo01/middlewares"
"github.com/gin-gonic/gin"
"net/http"
)
func DefaultRoutersInit (r *gin.Engine) {
defaultRouters := r.Group("/")
// 配置全局中间件
defaultRouters.Use(middlewares.InitMiddleware)
{
defaultRouters.GET("/", func(c *gin.Context) {
// 获取中间件的数据
username, _ := c.Get("username")
fmt.Println(username)
// 类型断言
v, ok := username.(string)
if ok == true {
fmt.Println("用户名称:" +v)
} else {
fmt.Println("获取用户失败")
}
c.String(http.StatusOK, "首页")
})
// 用户列表
// UserIndex() 执行方法,不加括号是注册方法
defaultRouters.GET("/user", _default.UserController{
}.Index)
// 添加用户
defaultRouters.GET("/user/add", _default.UserController{
}.Add)
}
}
7. 自定义 Model;
关于 Model
如果应用非常简单的话,可以在 Controller 里面处理常见的业务逻辑。但是如果有一个功能想在多个控制器、或者多个模板里面复用的话,就可以把公共的功能单独抽取出来作为一个模块(Model)。Model 是逐步抽象的过程,一般会在 Model 里封装一些公共的方法让不同 Controller 使用,也可以砸 Model 中实现和数据打交道
文件
~/go/go-gin2/gindemo01/models/tools.go
package models
import (
"time"
)
// 时间转化成日期
func UnixToTime(timestamp int) string {
t := time.Unix(int64(timestamp), 0)
return t.Format("2006-01-02 15:04:05")
}
- 调用:
time := models.UnixToTime(1653639435)
fmt.Println("当前时间:"+time)
8. Session 获取:
Gin 没有提供 session 相关的文档,需要第三方 session 中间件来实现
安装方式:
go get github.com/gin-contrib/sessions
文件
~/go/go-gin2/gindemo01/main.go
package main
import (
"gindemo01/routers"
"github.com/gin-contrib/sessions/redis"
"github.com/gin-gonic/gin"
"github.com/gin-contrib/sessions"
"github.com/gin-contrib/sessions/cookie"
)
func main() {
// 创建默认路由引擎
var r = gin.Default()
// 配置 session 中间件
// 创建基于 cookie 的存储引擎,secret 参数是用于加密的秘钥
store := cookie.NewStore([]byte("secret"))
// 配置 session 中间件,store 是前面创建的存储引擎
r.Use(sessions.Sessions("mysession", store))
//配置 redis 存储引擎
store_redis, _ := redis.NewStore(10, "tcp", "localhost:6379", "", []byte("secret"))
r.Use(sessions.Sessions("mysession_redis", store_redis))
//路由分组
routers.DefaultRoutersInit(r)
routers.ApiRoutersInit(r)
// 创建 web 服务,默认 8080 端口
r.Run(":8001")
}
- 文件
~/go/go-gin2/gindemo01/controllers/default/userController.go
package _default
import (
"fmt"
"gindemo01/models"
"github.com/gin-contrib/sessions"
"github.com/gin-gonic/gin"
"net/http"
)
type UserController struct{
BaseController // 控制器继承
}
func (con UserController) Index (c *gin.Context) {
session := sessions.Default(c)
// 设置过期时间等
session.Options(sessions.Options{
MaxAge: 3600 * 6,
})
// 设置 session
session.Set("username1", "hua")
session.Save() //保存
// 获取 session
username := session.Get("username1")
c.String(http.StatusOK, "username=%v", username)
time := models.UnixToTime(1653639435)
fmt.Println("当前时间:"+time)
c.String(http.StatusOK, "用户列表")
}
func (con UserController) Add (c *gin.Context) {
c.String(http.StatusOK, "添加用户")
con.success(c)
}
9. 使用 GORM 操作数据库;
简介
GORM 是 golang 的一个 orm 框架,orm 是通过实例对象的语法,完成关系型数据库的操作的技术、是对象映射的缩写
文件
~/go/go-gin2/gindemo01/models/core.go
package models
import (
"fmt"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
var DB *gorm.DB
var err error
func init () {
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
dsn := "root:[email protected](127.0.0.1:3306)/test?charset=utf8mb4&parseTime=True&loc=Local"
DB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{
})
if err != nil {
fmt.Println(err)
}
}
- 文件
~/go/go-gin2/gindemo01/models/user.go
package models
// 结构体首字母大写
// 和数据表名称对应,比如表为 user_info 结构体定义为 UserInfo
// 默认情况下表名是接口体的复数形式
type User struct {
Id int
Username string
Age int
Email string
AddTime string
}
// 修改结构体的默认表名称,配置数据表
func (User) TableName() string {
return "user"
}
- 文件
~/go/go-gin2/gindemo01/controllers/default/userController.go
package _default
import (
"gindemo01/models"
"github.com/gin-gonic/gin"
"net/http"
)
type UserController struct{
BaseController // 控制器继承
}
func (con UserController) Index (c *gin.Context) {
user := []models.User{
} // 定义切片
//models.DB.Find(&user)
models.DB.Where("age>20").Find(&user)
c.JSON(http.StatusOK, gin.H{
"result" : user,
})
}
func (con UserController) Add (c *gin.Context) {
c.String(http.StatusOK, "添加用户")
con.success(c)
}
func (con UserController) Edit (c *gin.Context) {
c.String(http.StatusOK, "修改用户")
}
func (con UserController) Delete (c *gin.Context) {
c.String(http.StatusOK, "删除用户")
}
边栏推荐
- golang中的atomic,以及CAS操作
- 1123. 最深叶节点的最近公共祖先
- LeetCode. 剑指offer 62. 圆圈中最后剩下的数
- 如何管理分布式团队?
- 剑指 Offer II 035. 最小时间差-快速排序加数据转换
- How to manage distributed teams?
- Neon Optimization: performance optimization FAQ QA
- Dark horse notes - exception handling
- Taro中添加小程序 “lazyCodeLoading“: “requiredComponents“,
- THREE.AxesHelper is not a constructor
猜你喜欢
对C语言数组的再认识
2022 Google CTF SEGFAULT LABYRINTH wp
[advanced C language] 8 written questions of pointer
Yunna | work order management software, work order management software app
字节P7专业级讲解:接口测试常用工具及测试方法,福利文
JTAG debugging experience of arm bare board debugging
AI 从代码中自动生成注释文档
405 method not allowed appears when the third party jumps to the website
Comparison of picture beds of free white whoring
Make Jar, Not War
随机推荐
搭建【Redis in CentOS7.x】
golang中的atomic,以及CAS操作
机器学习:随机梯度下降(SGD)与梯度下降(GD)的区别与代码实现。
Dark horse notes - exception handling
免费白嫖的图床对比
Amway wave C2 tools
Force buckle 1037 Effective boomerang
云呐-工单管理制度及流程,工单管理规范
安利一波C2工具
THREE. AxesHelper is not a constructor
1123. 最深叶节点的最近公共祖先
Transformation transformation operator
Lldp compatible CDP function configuration
黑马笔记---创建不可变集合与Stream流
ClickHouse字段分组聚合、按照任意时间段粒度查询SQL
各种语言,软件,系统的国内镜像,收藏这一个仓库就够了: Thanks-Mirror
Taro2.* applet configuration sharing wechat circle of friends
NEON优化:矩阵转置的指令优化案例
LeetCode:1175. Prime permutation
一起看看matlab工具箱内部是如何实现BP神经网络的