参考 GORM 指南

参考 Gin Web Framework

目录结构

mvn grpc插件_mysql

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")
}

 构建并运行

mvn grpc插件_json_02

 测试

mvn grpc插件_User_03

 渲染 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>

测试:

mvn grpc插件_mysql_04

 

mvn grpc插件_mysql_05