简单Go项目

好的,以下是替换为模块 github.com/muyiacc/gin-gorm-demo 的完整代码示例。

项目结构

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
gin-gorm-demo/
├── cmd/
│   └── root.go
├── config/
│   └── config.go
├── api/
│   ├── user_handler.go
│   └── routers.go
├── model/
│   └── user.go
├── main.go
└── config.toml

1. main.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
package main

import (
    "github.com/muyiacc/gin-gorm-demo/cmd"
)

func main() {
    if err := cmd.Init(); err != nil {
        panic(err)
    }

    r := cmd.SetupRouter()
    if err := r.Run(":" + cmd.viper.GetString("server.port")); err != nil {
        cmd.logger.Fatal("Failed to start server", zap.Error(err))
    }
}

2. cmd/root.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
package cmd

import (
    "fmt"
    "gorm.io/driver/mysql"
    "gorm.io/driver/postgres"
    "gorm.io/gorm"
    "github.com/gin-gonic/gin"
    "go.uber.org/zap"
    "github.com/muyiacc/gin-gorm-demo/api"
    "github.com/muyiacc/gin-gorm-demo/config"
    "github.com/muyiacc/gin-gorm-demo/model"
)

var (
    logger *zap.Logger
    db     *gorm.DB
)

func initDB(dbType, dsn string) (*gorm.DB, error) {
    var gormDB *gorm.DB
    var err error

    switch dbType {
    case "mysql":
        gormDB, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    case "postgres":
        gormDB, err = gorm.Open(postgres.Open(dsn), &gorm.Config{})
    default:
        return nil, fmt.Errorf("unsupported database type: %s", dbType)
    }

    return gormDB, err
}

func Init() error {
    var err error
    cfg, err := config.InitConfig()
    if err != nil {
        return err
    }

    // 初始化 logger
    logger, err = initLogger(cfg.Log.Level)
    if err != nil {
        return err
    }

    logger.Info("Starting application...")

    // 初始化数据库
    db, err = initDB(cfg.Database.Type, cfg.Database.Dsn)
    if err != nil {
        logger.Fatal("Failed to connect to database", zap.Error(err))
        return err
    }

    logger.Info("Database connection established")

    // 自动迁移
    if err := db.AutoMigrate(&model.User{}); err != nil {
        logger.Fatal("Failed to migrate database", zap.Error(err))
        return err
    }

    logger.Info("Database migration completed")

    return nil
}

func initLogger(level string) (*zap.Logger, error) {
    var logger *zap.Logger
    var err error

    switch level {
    case "debug":
        logger, err = zap.NewDevelopment()
    case "info":
        logger, err = zap.NewProduction()
    case "warn":
        logger, err = zap.NewProduction()
    case "error":
        logger, err = zap.NewProduction()
    default:
        logger, err = zap.NewProduction()
    }

    if err != nil {
        return nil, err
    }

    return logger, nil
}

func SetupRouter() *gin.Engine {
    r := gin.Default()
    api.RegisterUserRoutes(r, db, logger)
    return r
}

3. config/config.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package config

import (
    "github.com/spf13/viper"
)

type Config struct {
    Database struct {
        Type string `mapstructure:"type"`
        Dsn  string `mapstructure:"dsn"`
    } `mapstructure:"database"`
    Log struct {
        Level string `mapstructure:"level"`
    } `mapstructure:"log"`
    Server struct {
        Port string `mapstructure:"port"`
    } `mapstructure:"server"`
}

func InitConfig() (*Config, error) {
    var cfg Config

    viper.SetConfigName("config") // name of config file (without extension)
    viper.SetConfigType("toml")    // REQUIRED if the config file does not have the extension in the name
    viper.AddConfigPath(".")        // optionally look for config in the working directory

    if err := viper.ReadInConfig(); err != nil {
        return nil, err
    }

    if err := viper.Unmarshal(&cfg); err != nil {
        return nil, err
    }

    return &cfg, nil
}

4. api/user_handler.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
package api

import (
    "github.com/gin-gonic/gin"
    "gorm.io/gorm"
    "go.uber.org/zap"
    "github.com/muyiacc/gin-gorm-demo/model"
)

func RegisterUserRoutes(r *gin.Engine, db *gorm.DB, logger *zap.Logger) {
    r.POST("/users", func(c *gin.Context) {
        var user model.User
        if err := c.ShouldBindJSON(&user); err != nil {
            logger.Warn("Invalid input", zap.Error(err))
            c.JSON(400, gin.H{"error": "Invalid input"})
            return
        }
        
        if err := db.Create(&user).Error; err != nil {
            logger.Error("Failed to create user", zap.Error(err))
            c.JSON(500, gin.H{"error": "Failed to create user"})
            return
        }

        logger.Info("User created successfully", zap.String("username", user.Username))
        c.JSON(201, user)
    })
}

5. api/routers.go

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
package api

import "github.com/gin-gonic/gin"

func RegisterUserRoutes(r *gin.Engine, db *gorm.DB, logger *zap.Logger) {
    // 注册用户相关路由
    r.POST("/users", func(c *gin.Context) {
        // 处理用户创建
    })
}

6. model/user.go

1
2
3
4
5
6
7
8
9
package model

import "gorm.io/gorm"

type User struct {
    gorm.Model
    Username string `json:"username" gorm:"unique;not null"`
    Password string `json:"password" gorm:"not null"`
}

7. config.toml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
[database]
type = "mysql"  # 或 "postgres"
dsn = "user:password@tcp(localhost:3306)/dbname"  # MySQL 示例
# dsn = "host=localhost port=5432 user=user password=password dbname=dbname sslmode=disable"  # PostgreSQL 示例

[log]
level = "info"

[server]
port = "8080"

运行项目

确保你的 Go 环境已设置好,并根据你的数据库配置更新 config.toml 文件。然后运行项目:

1
go run main.go

总结

以上代码实现了一个完整的 Go 项目,模块名为 github.com/muyiacc/gin-gorm-demo,支持 MySQL 和 PostgreSQL 数据源,并使用 zap 进行日志记录。每个步骤都记录了相关的日志信息,便于调试和监控。

Oct 11, 2024 03:03 +0800
页面浏览量Loading
网站总访客数:Loading
网站总访问量:Loading

-->