Golang Gin 项目代码结构之共享 MySQL 数据库连接

文章目录

    想在 Golang Gin 项目中模仿 Laravel 的代码目录结构。参考了网上的一些做法,感觉使用全局变量共享 MySQL 数据库连接的方式最容易上手。

    虽然不利于进行单元测试,但是对于练手来说,确实最容易的体验方案。

    Gin 项目代码目录结构

    新建 models 目录,用于管理 Golang Gin 项目的数据库相关的操作,同时定义一批 model,即 struct。

    > mkdir models
    > touch models/kv.go
    > touch models/db.go
    > tree
    .
    ├── controllers
    │   └── hello.go
    ├── go.mod
    ├── go.sum
    ├── main.go
    ├── models
    │   ├── db.go
    │   └── kv.go
    ├── public
    │   └── js
    │       └── main.min.js
    └── views
        └── hello.html
    
    5 directories, 8 files
    

    注:这个结构不如我新整理的 gin 模仿 django 的目录结构清晰。

    models/db.go

    package models
    
    import (
    	"database/sql"
    	_ "github.com/go-sql-driver/mysql"
    	"log"
    )
    
    var db *sql.DB
    
    func InitDB(dataSourceName string) {
    	var err error
    	db, err = sql.Open("mysql", dataSourceName)
    
    	if err != nil {
    		log.Fatal("Error")
    	}
    
    	//defer db.Close()
    }
    

    models/kv.go 一个 model 样例

    package models
    
    type KV struct {
    	Id         int
    	Key        string
    	Value      string
    	Updated_at string
    }
    
    func GetValue(key string) (*KV, error) {
    	var kv KV
    	err := db.QueryRow("SELECT id, `key`, value, updated_at FROM kv where id = ?",
    		key).Scan(&kv.Id, &kv.Key, &kv.Value, &kv.Updated_at)
    	if err != nil {
    		panic(err.Error()) // proper error handling instead of panic in your app
    	}
    
    	db.Exec(`update kv 
    		set value = value + 1, updated_at = now() 
    		where id = ?`, key)
    
    	return &kv, err
    }
    

    main.go 中初始化 MySQL 数据库连接

    package main
    
    import (
    	"fmt"
    	"github.com/gin-gonic/gin"
    	"github.com/joho/godotenv"
    	"log"
    	"os"
    	"sunzhongwei.com/go_tool/controllers"
    	"sunzhongwei.com/go_tool/models"
    )
    
    func main() {
    	err := godotenv.Load("../.env")
    	if err != nil {
    		log.Fatal("Error loading .env file")
    	}
    	db_database := os.Getenv("DB_DATABASE")
    	db_username := os.Getenv("DB_USERNAME")
    	db_password := os.Getenv("DB_PASSWORD")
    	db_host := os.Getenv("DB_HOST")
    	db_port := os.Getenv("DB_PORT")
    	models.InitDB(fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&timeout=5000ms",
    		db_username, db_password, db_host, db_port, db_database))
    
    	router := gin.Default()
    	router.LoadHTMLGlob("views/*.html")
    	router.Static("/go/public", "./public")
    	router.GET("/hello", controllers.HelloIndex)
    	router.Run() // listen and serve on 0.0.0.0:8080
    }
    

    controllers/hello.go 中访问 model

    package controllers
    
    import (
    	"github.com/gin-gonic/gin"
    	"net/http"
    	"sunzhongwei.com/go_tool/models"
    )
    
    func HelloIndex(c *gin.Context) {
    	models.GetValue("2")
    	c.HTML(http.StatusOK, "hello.html", gin.H{})
    }
    

    参考

    总结了几种方式
    https://www.alexedwards.net/blog/organising-database-access

    关于作者 🌱

    我是来自山东烟台的一名开发者,有感兴趣的话题,或者软件开发需求,欢迎加微信 zhongwei 聊聊,或者关注我的个人公众号“大象工具”, 查看更多联系方式