参考 GORM 指南
参考 Gin Web Framework
目录结构
controller:负责请求转发,接受页面过来的参数,传给 Model 处理,接到返回值,再传给页面。
database:通过 gorm 连接数据库。
models:对应数据表的增删查改。
router:处理路由。
templates:HTML 模板。
定义路由
package router
import (
. "gin-mvc/controller"
"github.com/gin-gonic/gin"
)
/*
InitRouter 路由初始化
GET /FindUsers 请求将由 controller 下的 FindUsers 方法处理
*/
func InitRouter() *gin.Engine {
router := gin.Default()
router.GET("/findUsers", FindUsers)
return router
}
创建 User Model
package models
/*
GORM 倾向于约定,而不是配置。
默认情况下,GORM 使用 ID 作为主键,
使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,
并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。
例如,结构体 User 在 gorm 看来对应的表名应为 users,而不是 user
*/
type User struct {
ID int64 `json:"id"` // 列名为 `id`
Username string `json:"username"` // 列名为 `username`
Password string `json:"password"` // 列名为 `password`
}
连接数据库
package database
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql" // mysql 数据库驱动
"gorm.io/gorm" // 使用 gorm ,操作数据库的 orm 框架
"gorm.io/gorm/logger"
)
/*
go 访问权限:
变量名、函数名、常量名首字母大写,则可以被其他包访问,
如果首字母小写,则只能在本包中使用。
首字母大写为共有,首字母小写为私有。
*/
var Db *gorm.DB
/*
数据库初始化。
init() 表示包初始化的时候执行的函数, 如果函数名写成 main() , 会在操作数据的时候报错。
参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情。
*/
func init() {
// ----------------------- 日志设置 -----------------------
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold
LogLevel: logger.Silent, // Log level
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger
Colorful: false, // Disable color
},
)
// ----------------------- 连接数据库 -----------------------
var err error
Db, err = gorm.Open(mysql.New(mysql.Config{
DSN: "root:root@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local&timeout=10ms", // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: true, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{
Logger: newLogger,
})
if err != nil {
fmt.Printf("mysql connect error %v", err)
}
if Db.Error != nil {
fmt.Printf("database error %v", Db.Error)
}
// ----------------------- 连接池设置 -----------------------
sqlDB, err := Db.DB()
// SetMaxIdleConns 设置空闲连接池中连接的最大数量
sqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
sqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
sqlDB.SetConnMaxLifetime(time.Hour)
}
User Model 新增查询方法 FindUsers
package models
import (
orm "gin-mvc/database"
)
/*
GORM 倾向于约定,而不是配置。
默认情况下,GORM 使用 ID 作为主键,
使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,
并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。
例如,结构体 User 在 gorm 看来对应的表名应为 users,而不是 user
*/
type User struct {
ID int64 `json:"id"` // 列名为 `id`
Username string `json:"username"` // 列名为 `username`
Password string `json:"password"` // 列名为 `password`
}
/*
当return 后面为空时,函数声明时的 (users []User, err error) 会把 users,err 作为返回值;
当 return 不为空时,会把 return 后面的值作为返回值。
*/
// 列表
func (user *User) FindUsers() (users []User, err error) {
if err = orm.Db.Find(&users).Error; err != nil {
return
}
return
}
controller 调用 model 的方法
package controller
import (
model "gin-mvc/models"
"net/http"
"github.com/gin-gonic/gin"
)
/*
用户接口:
调用 user model FindUsers 方法返回用户列表
*/
func FindUsers(c *gin.Context) {
var user model.User
result, err := user.FindUsers()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": -1,
"msg": "not found",
"data": "",
"err": err,
})
return
}
c.JSON(http.StatusOK, gin.H{
"code": 1,
"msg": "success",
"data": result,
"err": "",
})
}
main.go
package main
import (
"gin-mvc/router"
)
func main() {
r := router.InitRouter()
r.Run(":8080")
}
构建并运行
测试
渲染 HTML 模板
修改 router.go :
package router
import (
. "gin-mvc/controller"
"github.com/gin-gonic/gin"
)
/*
InitRouter 路由初始化
*/
func InitRouter() *gin.Engine {
router := gin.Default()
// 加载 templates 文件夹下所有的 tmpl
router.LoadHTMLGlob("templates/*")
router.GET("/findUsers", FindUsers)
return router
}
控制器定义返回页面:
package controller
import (
model "gin-mvc/models"
"net/http"
"github.com/gin-gonic/gin"
)
/*
用户接口:
调用 user model FindUsers 方法返回用户列表
*/
func FindUsers(c *gin.Context) {
var user model.User
result, err := user.FindUsers()
if err != nil {
c.JSON(http.StatusOK, gin.H{
"code": -1,
"msg": "not found",
"data": "",
"err": err,
})
return
}
// c.JSON(http.StatusOK, gin.H{
// "code": 1,
// "msg": "success",
// "data": result,
// "err": "",
// })
// 指定渲染页面
c.HTML(http.StatusOK, "users.tmpl", gin.H{
"result": result,
})
}
users.tmpl:
<html>
<body>
{{ .result }}
</body>
</html>
测试: