当前位置:网站首页>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, "删除用户")
}
边栏推荐
- 【C语言进阶篇】指针的8道笔试题
- 机器学习:随机梯度下降(SGD)与梯度下降(GD)的区别与代码实现。
- The MySQL database in Alibaba cloud was attacked, and finally the data was found
- Send template message via wechat official account
- What are the differences between Oracle Linux and CentOS?
- 微信公众号发送模板消息
- Table table setting fillet
- Force buckle 1037 Effective boomerang
- 今日问题-2022/7/4 lambda体中修改String引用类型变量
- The cost of returning tables in MySQL
猜你喜欢
Byte P7 professional level explanation: common tools and test methods for interface testing, Freeman
今日问题-2022/7/4 lambda体中修改String引用类型变量
Instructions for using the domain analysis tool bloodhound
According to the analysis of the Internet industry in 2022, how to choose a suitable position?
2022 Google CTF SEGFAULT LABYRINTH wp
Comparison of picture beds of free white whoring
Transplant DAC chip mcp4725 to nuc980
Yunna | work order management measures, how to carry out work order management
免费白嫖的图床对比
HMM notes
随机推荐
Sword finger offer II 035 Minimum time difference - quick sort plus data conversion
POJ 3177 Redundant Paths POJ 3352 Road Construction(双连接)
黑马笔记---异常处理
Your cache folder contains root-owned files, due to a bug in npm ERR! previous versions of npm which
Force buckle 1037 Effective boomerang
图片打水印 缩放 和一个输入流的转换
Send template message via wechat official account
Neon Optimization: summary of performance optimization experience
What are the differences between Oracle Linux and CentOS?
1123. The nearest common ancestor of the deepest leaf node
C language instance_ five
Neon Optimization: performance optimization FAQ QA
C language instance_ three
Transformation transformation operator
Lldp compatible CDP function configuration
NEON优化:关于交叉存取与反向交叉存取
tansig和logsig的差异,为什么BP喜欢用tansig
Installation and testing of pyflink
[chip scheme design] pulse oximeter
第三方跳转网站 出现 405 Method Not Allowed