跳过正文
Background Image
  1. Posts/

Go:Web 简单后端搭建步骤

·437 字·3 分钟· loading · loading ·
yuzjing
作者
yuzjing
目录

🌐 项目目标
#

使用 Gin 框架搭建一个简单web服务.

🛠️ 项目结构
#

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
todo-api/
├── main.go                 # 入口文件
├── routes/
│   └── todo_routes.go    # 路由定义
├── models/
│   └── todo.go           # 数据结构
├── middleware/
│   └── logging.go        # 自定义中间件
├── config/
│   └── config.go         # 配置管理
└── go.mod                # Go 模块

📦 安装依赖
#

1
2
3
go mod init todo-api
go get -u github.com/gin-gonic/gin
go get -u github.com/jackc/pgx/v4

🧪 代码示例
#

1. 配置管理(config/config.go
#

1
2
3
4
5
6
package configimport "github.com/joho/godotenv"func LoadEnv() {
err := godotenv.Load()
if err != nil {
panic("Error loading .env file")
  }
}

2. 数据库连接(main.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
package mainimport (
"context"
"fmt"
"log"
"github.com/gin-gonic/gin"
"github.com/jackc/pgx/v4"
"todo-api/config"
"todo-api/routes"
)type Todo struct {
ID    int    `json:"id"`
Title string `json:"title"`
}func main() {
// 1. 加载环境变量
config.LoadEnv()// 2. 连接 PostgreSQL
connStr := fmt.Sprintf(
"postgres://%s:%s@%s:%s/%s?sslmode=disable",
os.Getenv("DB_USER"),
os.Getenv("DB_PASSWORD"),
os.Getenv("DB_HOST"),
os.Getenv("DB_PORT"),
os.Getenv("DB_NAME"),
)conn, err := pgx.Connect(context.Background(), connStr)
if err != nil {
log.Fatal("无法连接数据库:", err)
}
defer conn.Close(context.Background())// 3. 创建 Gin 应用
r := gin.Default()// 4. 注册路由
todoRoutes := routes.TodoRoutes{DB: conn}
r.POST("/todos", todoRoutes.CreateTodo)
r.GET("/todos", todoRoutes.GetAllTodos)// 5. 启动服务
r.Run(":8080")
}

3. 路由实现(routes/todo_routes.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
package routesimport (
"github.com/gin-gonic/gin"
"todo-api/models"
)type TodoRoutes struct {
DB *pgx.Conn
}func (tr *TodoRoutes) CreateTodo(c *gin.Context) {
var todo models.Todo
if err := c.ShouldBindJSON(&todo); err != nil {
c.JSON(400, gin.H{"error": err.Error()})
return
}_, err := tr.DB.Exec(context.Background(), "INSERT INTO todos (title) VALUES ($1)", todo.Title)
if err != nil {
    c.JSON(500, gin.H{"error": "数据库操作失败"})
    return
}

c.JSON(201, gin.H{"message": "成功创建任务"})
_, err := tr.DB.Exec(context.Background(), "INSERT INTO todos (title) VALUES ($1)", todo.Title)
if err != nil {
    c.JSON(500, gin.H{"error": "数据库操作失败"})
    return
}

c.JSON(201, gin.H{"message": "成功创建任务"})
}func (tr *TodoRoutes) GetAllTodos(c *gin.Context) {
rows, err := tr.DB.Query(context.Background(), "SELECT id, title FROM todos")
if err != nil {
c.JSON(500, gin.H{"error": "查询失败"})
return
}var todos []models.Todo
for rows.Next() {
    var t models.Todo
    if err := rows.Scan(&t.ID, &t.Title); err != nil {
        c.JSON(500, gin.H{"error": "解析结果失败"})
        return
    }
    todos = append(todos, t)
}

c.JSON(200, todos)
var todos []models.Todo
for rows.Next() {
    var t models.Todo
    if err := rows.Scan(&t.ID, &t.Title); err != nil {
        c.JSON(500, gin.H{"error": "解析结果失败"})
        return
    }
    todos = append(todos, t)
}

c.JSON(200, todos)
}