Go语言实战案例:执行基本的增删改查

在数据库开发中,最基础的操作就是 增(Create)、查(Read)、改(Update)、删(Delete) ,即 CRUD 。

Go 语言通过 database/sql 包和 MySQL 驱动,可以很方便地实现这些功能。

本篇我们将在 上一节"连接 MySQL" 的基础上,扩展实现 完整的 CRUD 案例。


一、准备工作

1. 数据库与表

假设我们已经创建好数据库和表(go_demo 数据库中的 users 表):

sql 复制代码
CREATE DATABASE go_demo;
USE go_demo;

CREATE TABLE users (
    id INT PRIMARY KEY AUTO_INCREMENT,
    name VARCHAR(50),
    age INT
);

2. 安装 MySQL 驱动

如果还没安装:

go 复制代码
go get -u github.com/go-sql-driver/mysql

二、代码实现

main.go:

go 复制代码
package main

import (
    "database/sql"
    "fmt"
    "log"

    _ "github.com/go-sql-driver/mysql"
)

var db *sql.DB

func initDB() {
    var err error
    dsn := "root:password@tcp(127.0.0.1:3306)/go_demo?charset=utf8mb4&parseTime=True&loc=Local"
    db, err = sql.Open("mysql", dsn)
    if err != nil {
        log.Fatalf("连接数据库失败: %v", err)
    }

    if err := db.Ping(); err != nil {
        log.Fatalf("无法连接到数据库: %v", err)
    }
    fmt.Println("数据库连接成功!")
}

// Create - 插入数据
func createUser(name string, age int) {
    result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", name, age)
    if err != nil {
        log.Fatalf("插入数据失败: %v", err)
    }
    id, _ := result.LastInsertId()
    fmt.Printf("新增用户成功,ID = %d\n", id)
}

// Read - 查询数据
func getUsers() {
    rows, err := db.Query("SELECT id, name, age FROM users")
    if err != nil {
        log.Fatalf("查询失败: %v", err)
    }
    defer rows.Close()

    fmt.Println("用户列表:")
    for rows.Next() {
        var id, age int
        var name string
        if err := rows.Scan(&id, &name, &age); err != nil {
            log.Fatalf("读取数据失败: %v", err)
        }
        fmt.Printf("ID: %d, 姓名: %s, 年龄: %d\n", id, name, age)
    }
}

// Update - 更新数据
func updateUser(id int, newAge int) {
    result, err := db.Exec("UPDATE users SET age = ? WHERE id = ?", newAge, id)
    if err != nil {
        log.Fatalf("更新数据失败: %v", err)
    }
    rowsAffected, _ := result.RowsAffected()
    fmt.Printf("更新完成,影响行数: %d\n", rowsAffected)
}

// Delete - 删除数据
func deleteUser(id int) {
    result, err := db.Exec("DELETE FROM users WHERE id = ?", id)
    if err != nil {
        log.Fatalf("删除数据失败: %v", err)
    }
    rowsAffected, _ := result.RowsAffected()
    fmt.Printf("删除完成,影响行数: %d\n", rowsAffected)
}

func main() {
    initDB()

    // 增
    createUser("Alice", 25)
    createUser("Bob", 30)

    // 查
    getUsers()

    // 改
    updateUser(1, 26)

    // 查
    getUsers()

    // 删
    deleteUser(2)

    // 查
    getUsers()
}

三、运行结果

假设我们执行:

go 复制代码
go run main.go

输出可能是:

makefile 复制代码
数据库连接成功!
新增用户成功,ID = 1
新增用户成功,ID = 2
用户列表:
ID: 1, 姓名: Alice, 年龄: 25
ID: 2, 姓名: Bob, 年龄: 30
更新完成,影响行数: 1
用户列表:
ID: 1, 姓名: Alice, 年龄: 26
ID: 2, 姓名: Bob, 年龄: 30
删除完成,影响行数: 1
用户列表:
ID: 1, 姓名: Alice, 年龄: 26

四、注意事项

    1. 参数化查询

    使用 ? 占位符,可以有效防止 SQL 注入。

    1. 错误处理

    查询、更新、插入、删除时都应检查 err。

    1. 连接池

    在生产环境中,建议配置连接池:

    scss 复制代码
    db.SetMaxOpenConns(10)
    db.SetMaxIdleConns(5)
    1. 事务支持

    如果多条 SQL 需要保证原子性,应使用 db.Begin() 开启事务。


五、总结

  • • Go 使用 database/sql + MySQL 驱动可以很方便地执行 CRUD 操作。
  • • 推荐使用参数化查询,避免 SQL 注入。
  • • 在生产中,要结合事务、连接池和错误重试机制,确保数据安全性与稳定性。

相关推荐
雾行0x0014 分钟前
粗排:如何在毫秒级筛出值得精排的内容?
后端·架构
D1213815 分钟前
从零用 C++17 写一个 API 网关:线程模型、控制面分离,以及三个真实 Bug
后端
Scene21615 分钟前
AgentScope Java 进阶:2.如何精准定义问题类型与处理“不确定性”?
后端
用户3459668152116 分钟前
在嵌入式 Linux 摄像头上跑 WebRTC:metaRTC 8.0 的 8 个坑与解法
后端
今天早睡19 分钟前
用 State、Reducer 和条件边搭出可控循环
后端
站大爷IP19 分钟前
Python的字符串格式化把我坑惨了,原来f-string和format的区别这么大
后端
雾行0x0022 分钟前
精排:推荐系统如何给内容打分?从多目标预估到分数融合
后端·架构
今天早睡23 分钟前
Checkpointer 和 thread_id 如何让状态跨调用延续
后端
用户4233412461924 分钟前
Redis 缓存穿透、击穿、雪崩,一次性讲清楚
后端
GlobalTradercrb27 分钟前
独立站SEO先写博客还是先优化产品页?看站点阶段
数据库·人工智能·google·pdf·go·seo