This commit is contained in:
oneao committed 2025-11-04 17:32:32 +08:00
1 parent c0ff3ce883
commit 69d03709ba
41 files changed
+5352 -67

No files matched your search

+2 -2
View File
@@ -3,7 +3,7 @@ package main
import (
"base-go-v2/internal/api"
"base-go-v2/internal/config"
"base-go-v2/internal/database"
"base-go-v2/internal/db"
"base-go-v2/internal/logx"
"fmt"
"github.com/valyala/fasthttp"
@@ -17,7 +17,7 @@ func main() {
}
// 初始化数据库
if err := database.InitDb(); err != nil {
if err := db.InitDb(); err != nil {
log.Fatalf("加载数据库配置失败: %v", err)
}
+1
View File
@@ -13,6 +13,7 @@ require (
github.com/andybalholm/brotli v1.2.0 // indirect
github.com/fsnotify/fsnotify v1.9.0 // indirect
github.com/go-viper/mapstructure/v2 v2.4.0 // indirect
github.com/jmoiron/sqlx v1.4.0 // indirect
github.com/klauspost/compress v1.18.1 // indirect
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
github.com/sagikazarmark/locafero v0.12.0 // indirect
+5
View File
@@ -1,15 +1,20 @@
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs=
github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o=
github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY=
github.com/klauspost/compress v1.18.1 h1:bcSGx7UbpBqMChDtsF28Lw6v/G94LPrrbMbdC3JH2co=
github.com/klauspost/compress v1.18.1/go.mod h1:ZQFFVG+MdnR0P+l6wpXgIL4NTtwiKIdBnrBd8Nrxr+0=
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
@@ -1,5 +1,27 @@
package auth
func InitAuthRouter() {
import (
response "base-go-v2/internal/reponse"
"base-go-v2/internal/router"
)
func InitAuthRouter(r *router.Router) {
group := r.Group("auth")
group.POST("/login/default", loginDefault)
}
// 默认登录
func loginDefault(c *router.Context) error {
return response.Success(c).Send()
}
// 注册
func registerDefault(c *router.Context) error {
var req struct {
Email string `json:"email"`
Password string `json:"password"`
}
if err := c.BindJSON(&req); err != nil {
}
}
@@ -1,15 +1,15 @@
package database
package db
import (
"base-go-v2/internal/config"
"database/sql"
"fmt"
"time"
"github.com/jmoiron/sqlx"
_ "github.com/lib/pq"
)
var DB *sql.DB
var DB *sqlx.DB
var defaultPoolConfig = struct {
MaxOpenConns int
@@ -28,7 +28,7 @@ func InitDb() error {
dsn := fmt.Sprintf("host=%s port=%d user=%s password=%s dbname=%s sslmode=disable",
d.Host, d.Port, d.User, d.Password, d.Dbname)
db, err := sql.Open("postgres", dsn)
db, err := sqlx.Connect("postgres", dsn)
if err != nil {
return fmt.Errorf("打开数据库失败: %w", err)
}
@@ -60,5 +60,6 @@ func InitDb() error {
fmt.Printf("✅ 数据库连接成功:%s:%d/%s\n", d.Host, d.Port, d.Dbname)
DB = db
return nil
}
@@ -0,0 +1,61 @@
package db
import (
"fmt"
)
// DeleteOne 根据主键删除单条记录
func DeleteOne(table string, pkColumn string, pkValue interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
query := fmt.Sprintf("DELETE FROM %s WHERE %s=$1", table, pkColumn)
res, err := tx.Exec(query, pkValue)
if err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return res.RowsAffected()
}
// DeleteBatch 根据主键批量删除记录
func DeleteBatch(table string, pkColumn string, pkValues []interface{}) (int64, error) {
if len(pkValues) == 0 {
return 0, nil
}
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
total := int64(0)
for _, pk := range pkValues {
query := fmt.Sprintf("DELETE FROM %s WHERE %s=$1", table, pkColumn)
res, err := tx.Exec(query, pk)
if err != nil {
tx.Rollback()
return 0, err
}
rows, err := res.RowsAffected()
if err != nil {
tx.Rollback()
return 0, err
}
total += rows
}
if err := tx.Commit(); err != nil {
return 0, err
}
return total, nil
}
@@ -0,0 +1,146 @@
package db
import (
"fmt"
"strings"
)
// ---------------- 内部辅助函数 ----------------
// buildInsertSQL 构建插入 SQL 和参数
func buildInsertSQL(table string, data map[string]interface{}, returning string) (string, []interface{}) {
columns := make([]string, 0, len(data))
placeholders := make([]string, 0, len(data))
values := make([]interface{}, 0, len(data))
i := 1
for k, v := range data {
columns = append(columns, k)
placeholders = append(placeholders, fmt.Sprintf("$%d", i))
values = append(values, v)
i++
}
sql := fmt.Sprintf("INSERT INTO %s (%s) VALUES (%s)", table,
strings.Join(columns, ","), strings.Join(placeholders, ","))
if returning != "" {
sql += " RETURNING " + returning
}
return sql, values
}
// ---------------- 公共方法 ----------------
// InsertOne 插入单条记录,返回受影响行数
func InsertOne(table string, data map[string]interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
sql, values := buildInsertSQL(table, data, "")
res, err := tx.Exec(sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return res.RowsAffected()
}
// InsertBatch 批量插入,返回总受影响行数
func InsertBatch(table string, dataList []map[string]interface{}) (int64, error) {
if len(dataList) == 0 {
return 0, nil
}
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
total := int64(0)
for _, data := range dataList {
sql, values := buildInsertSQL(table, data, "")
res, err := tx.Exec(sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
rows, err := res.RowsAffected()
if err != nil {
tx.Rollback()
return 0, err
}
total += rows
}
if err := tx.Commit(); err != nil {
return 0, err
}
return total, nil
}
// InsertOneReturnPK 插入单条记录,返回主键值
func InsertOneReturnPK(table string, pkColumn string, data map[string]interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
sql, values := buildInsertSQL(table, data, pkColumn)
var pk int64
err = tx.Get(&pk, sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return pk, nil
}
// InsertBatchReturnPK 批量插入多条记录,返回主键数组
func InsertBatchReturnPK(table string, pkColumn string, dataList []map[string]interface{}) ([]int64, error) {
if len(dataList) == 0 {
return nil, nil
}
tx, err := DB.Beginx()
if err != nil {
return nil, err
}
var pkList []int64
for _, data := range dataList {
sql, values := buildInsertSQL(table, data, pkColumn)
var pk int64
err := tx.Get(&pk, sql, values...)
if err != nil {
tx.Rollback()
return nil, err
}
pkList = append(pkList, pk)
}
if err := tx.Commit(); err != nil {
return nil, err
}
return pkList, nil
}
@@ -0,0 +1,96 @@
package db
import (
"fmt"
"strings"
)
// ---------------- 通用查询方法 ----------------
// GetOne 根据主键查询单条记录,返回 map[string]interface{}
func GetOne(table string, pkColumn string, pkValue interface{}) (map[string]interface{}, error) {
query := fmt.Sprintf("SELECT * FROM %s WHERE %s=$1", table, pkColumn)
row := make(map[string]interface{})
err := DB.Get(&row, query, pkValue)
if err != nil {
return nil, err
}
return row, nil
}
// GetBatch 根据主键批量查询,返回 []map[string]interface{}
func GetBatch(table string, pkColumn string, pkValues []interface{}) ([]map[string]interface{}, error) {
if len(pkValues) == 0 {
return nil, nil
}
var rows []map[string]interface{}
// 构建 IN 占位符
placeholders := make([]string, len(pkValues))
for i := range pkValues {
placeholders[i] = fmt.Sprintf("$%d", i+1)
}
query := fmt.Sprintf("SELECT * FROM %s WHERE %s IN (%s)", table, pkColumn, strings.Join(placeholders, ","))
err := DB.Select(&rows, query, pkValues...)
if err != nil {
return nil, err
}
return rows, nil
}
// Find 根据条件查询多条记录,可选排序
// conditions: map[column]value, 将以 AND 拼接
// orderBy: 可选排序字段,如 "created_at ASC",为空默认 "b_id DESC"
func Find(table string, conditions map[string]interface{}, orderBy ...string) ([]map[string]interface{}, error) {
if len(conditions) == 0 {
return nil, fmt.Errorf("查询条件不能为空")
}
var whereParts []string
var values []interface{}
i := 1
for k, v := range conditions {
whereParts = append(whereParts, fmt.Sprintf("%s=$%d", k, i))
values = append(values, v)
i++
}
query := fmt.Sprintf("SELECT * FROM %s WHERE %s", table, strings.Join(whereParts, " AND "))
order := "b_id DESC"
if len(orderBy) > 0 && orderBy[0] != "" {
order = orderBy[0]
}
query += " ORDER BY " + order
var rows []map[string]interface{}
err := DB.Select(&rows, query, values...)
if err != nil {
return nil, err
}
return rows, nil
}
// FindAll 查询整个表,可选排序
func FindAll(table string, orderBy ...string) ([]map[string]interface{}, error) {
query := fmt.Sprintf("SELECT * FROM %s", table)
order := "b_id DESC"
if len(orderBy) > 0 && orderBy[0] != "" {
order = orderBy[0]
}
query += " ORDER BY " + order
var rows []map[string]interface{}
err := DB.Select(&rows, query)
if err != nil {
return nil, err
}
return rows, nil
}
@@ -0,0 +1,103 @@
package db
import (
"fmt"
"strings"
)
// ---------------- 内部辅助函数 ----------------
// buildUpdateSQL 构建 UPDATE SQL 和参数
// idColumn: 主键列名
func buildUpdateSQL(table string, data map[string]interface{}, idColumn string) (string, []interface{}) {
var setParts []string
var values []interface{}
i := 1
for k, v := range data {
setParts = append(setParts, fmt.Sprintf("%s=$%d", k, i))
values = append(values, v)
i++
}
// WHERE id = $n
sql := fmt.Sprintf("UPDATE %s SET %s WHERE %s=$%d",
table,
strings.Join(setParts, ", "),
idColumn,
i,
)
return sql, values
}
// ---------------- 公共方法 ----------------
// UpdateOne 更新单条记录,按主键 idColumn
func UpdateOne(table string, idColumn string, id interface{}, data map[string]interface{}) (int64, error) {
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
sql, values := buildUpdateSQL(table, data, idColumn)
values = append(values, id) // 最后一个参数是 id
res, err := tx.Exec(sql, values...)
if err != nil {
err := tx.Rollback()
if err != nil {
return 0, err
}
return 0, err
}
if err := tx.Commit(); err != nil {
return 0, err
}
return res.RowsAffected()
}
// UpdateBatch 批量更新,dataList 中每个 map 必须包含主键 idColumn
func UpdateBatch(table string, idColumn string, dataList []map[string]interface{}) (int64, error) {
if len(dataList) == 0 {
return 0, nil
}
tx, err := DB.Beginx()
if err != nil {
return 0, err
}
total := int64(0)
for _, data := range dataList {
idValue, ok := data[idColumn]
if !ok {
tx.Rollback()
return 0, fmt.Errorf("缺少主键列 %s", idColumn)
}
// 移除主键列,否则会重复在 SET 中出现
delete(data, idColumn)
sql, values := buildUpdateSQL(table, data, idColumn)
values = append(values, idValue)
res, err := tx.Exec(sql, values...)
if err != nil {
tx.Rollback()
return 0, err
}
rows, err := res.RowsAffected()
if err != nil {
tx.Rollback()
return 0, err
}
total += rows
}
if err := tx.Commit(); err != nil {
return 0, err
}
return total, nil
}
Whitespace-only changes.
Whitespace-only changes.
Whitespace-only changes.