Go语言数据库操作与ORM实践
2026/5/15 22:35:22 网站建设 项目流程

Go语言数据库操作与ORM实践

一、数据库基础

Go语言提供了database/sql包作为数据库操作的标准接口,支持多种数据库驱动。

常用数据库驱动

数据库驱动包
MySQLgithub.com/go-sql-driver/mysql
PostgreSQLgithub.com/lib/pq
SQLitegithub.com/mattn/go-sqlite3
SQL Servergithub.com/denisenkom/go-mssqldb

基础连接

package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) func main() { // 连接字符串格式: user:password@tcp(host:port)/database dsn := "root:password@tcp(localhost:3306)/example_db" db, err := sql.Open("mysql", dsn) if err != nil { fmt.Printf("Failed to open database: %v\n", err) return } defer db.Close() // 验证连接 err = db.Ping() if err != nil { fmt.Printf("Failed to ping database: %v\n", err) return } fmt.Println("Database connection successful") }

二、CRUD操作

查询数据

package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" ) type User struct { ID int Name string Age int } func main() { db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/example_db") if err != nil { panic(err) } defer db.Close() // 单行查询 var user User err = db.QueryRow("SELECT id, name, age FROM users WHERE id = ?", 1).Scan(&user.ID, &user.Name, &user.Age) if err != nil { if err == sql.ErrNoRows { fmt.Println("User not found") } else { fmt.Printf("Query failed: %v\n", err) } return } fmt.Printf("User: %+v\n", user) // 多行查询 rows, err := db.Query("SELECT id, name, age FROM users WHERE age > ?", 18) if err != nil { fmt.Printf("Query failed: %v\n", err) return } defer rows.Close() var users []User for rows.Next() { var u User err = rows.Scan(&u.ID, &u.Name, &u.Age) if err != nil { fmt.Printf("Scan failed: %v\n", err) return } users = append(users, u) } fmt.Printf("Users: %+v\n", users) }

插入数据

func createUser(db *sql.DB, name string, age int) (int64, error) { result, err := db.Exec("INSERT INTO users (name, age) VALUES (?, ?)", name, age) if err != nil { return 0, err } // 获取插入的ID id, err := result.LastInsertId() if err != nil { return 0, err } return id, nil }

更新数据

func updateUser(db *sql.DB, id int, name string, age int) (int64, error) { result, err := db.Exec("UPDATE users SET name = ?, age = ? WHERE id = ?", name, age, id) if err != nil { return 0, err } // 获取影响的行数 rowsAffected, err := result.RowsAffected() if err != nil { return 0, err } return rowsAffected, nil }

删除数据

func deleteUser(db *sql.DB, id int) (int64, error) { result, err := db.Exec("DELETE FROM users WHERE id = ?", id) if err != nil { return 0, err } rowsAffected, err := result.RowsAffected() if err != nil { return 0, err } return rowsAffected, nil }

三、ORM框架

GORM基础

go get gorm.io/gorm go get gorm.io/driver/mysql
package main import ( "fmt" "gorm.io/driver/mysql" "gorm.io/gorm" ) type User struct { gorm.Model Name string Age int } func main() { dsn := "root:password@tcp(localhost:3306)/example_db?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic("failed to connect database") } // 自动迁移表结构 db.AutoMigrate(&User{}) // 创建记录 user := User{Name: "John", Age: 30} result := db.Create(&user) fmt.Printf("Created user with ID: %d, Error: %v\n", user.ID, result.Error) // 查询记录 var foundUser User db.First(&foundUser, 1) // 根据主键查询 fmt.Printf("Found user: %+v\n", foundUser) // 更新记录 db.Model(&foundUser).Update("Age", 31) // 删除记录 db.Delete(&foundUser) }

GORM查询

// 条件查询 var users []User db.Where("age > ?", 18).Find(&users) // 链式查询 db.Where("name LIKE ?", "%John%").Order("age DESC").Limit(10).Find(&users) // 关联查询 type Order struct { gorm.Model UserID uint Amount float64 } var orders []Order db.Preload("User").Find(&orders)

GORM事务

func transfer(db *gorm.DB, fromID, toID uint, amount float64) error { return db.Transaction(func(tx *gorm.DB) error { // 扣减余额 if err := tx.Model(&User{}).Where("id = ?", fromID).Update("balance", gorm.Expr("balance - ?", amount)).Error; err != nil { return err } // 增加余额 if err := tx.Model(&User{}).Where("id = ?", toID).Update("balance", gorm.Expr("balance + ?", amount)).Error; err != nil { return err } // 返回nil提交事务 return nil }) }

四、数据库连接池

连接池配置

package main import ( "database/sql" "time" _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open("mysql", "root:password@tcp(localhost:3306)/example_db") if err != nil { panic(err) } // 设置连接池参数 db.SetMaxOpenConns(100) // 最大打开连接数 db.SetMaxIdleConns(10) // 最大空闲连接数 db.SetConnMaxLifetime(30 * time.Minute) // 连接最大存活时间 db.SetConnMaxIdleTime(10 * time.Minute) // 连接最大空闲时间 defer db.Close() }

连接池监控

func monitorPool(db *sql.DB) { stats := db.Stats() fmt.Printf("Open connections: %d\n", stats.OpenConnections) fmt.Printf("Idle connections: %d\n", stats.Idle) fmt.Printf("Connections used: %d\n", stats.InUse) fmt.Printf("Wait count: %d\n", stats.WaitCount) fmt.Printf("Wait duration: %v\n", stats.WaitDuration) }

五、数据库迁移

使用go-migrate

go install -tags 'mysql' github.com/golang-migrate/migrate/v4/cmd/migrate@latest

创建迁移文件:

migrate create -ext sql -dir migrations -seq create_users_table

迁移文件示例:

-- migrations/000001_create_users_table.up.sql CREATE TABLE users ( id INT AUTO_INCREMENT PRIMARY KEY, name VARCHAR(100) NOT NULL, age INT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ); -- migrations/000001_create_users_table.down.sql DROP TABLE users;

运行迁移:

migrate -path migrations -database "mysql://root:password@tcp(localhost:3306)/example_db" up

六、数据库事务

原生事务

func doTransaction(db *sql.DB) error { tx, err := db.Begin() if err != nil { return err } defer func() { if r := recover(); r != nil { tx.Rollback() } }() // 执行SQL语句 _, err = tx.Exec("INSERT INTO users (name, age) VALUES (?, ?)", "Alice", 25) if err != nil { tx.Rollback() return err } _, err = tx.Exec("UPDATE accounts SET balance = balance - 100 WHERE user_id = ?", 1) if err != nil { tx.Rollback() return err } return tx.Commit() }

Savepoint

func withSavepoint(db *sql.DB) error { tx, err := db.Begin() if err != nil { return err } // 设置savepoint _, err = tx.Exec("SAVEPOINT sp1") if err != nil { tx.Rollback() return err } // 执行操作 _, err = tx.Exec("INSERT INTO users (name) VALUES (?)", "Test") if err != nil { tx.Exec("ROLLBACK TO SAVEPOINT sp1") // 继续其他操作... } return tx.Commit() }

七、SQL注入防护

参数化查询

// 安全:使用参数化查询 func safeQuery(db *sql.DB, username string) ([]User, error) { rows, err := db.Query("SELECT * FROM users WHERE username = ?", username) if err != nil { return nil, err } defer rows.Close() var users []User for rows.Next() { var u User err = rows.Scan(&u.ID, &u.Name) if err != nil { return nil, err } users = append(users, u) } return users, nil } // 不安全:字符串拼接 func unsafeQuery(db *sql.DB, username string) ([]User, error) { // 危险!可能导致SQL注入 query := fmt.Sprintf("SELECT * FROM users WHERE username = '%s'", username) rows, err := db.Query(query) // ... }

ORM自动防护

// GORM自动使用参数化查询 func gormQuery(db *gorm.DB, username string) ([]User, error) { var users []User // GORM自动处理参数化 err := db.Where("username = ?", username).Find(&users).Error return users, err }

八、数据库优化

查询优化

// 添加索引 db.Exec("CREATE INDEX idx_users_age ON users(age)") // 使用覆盖索引 rows, err := db.Query("SELECT id, name FROM users USE INDEX (idx_users_age) WHERE age > ?", 18) // 分页查询 rows, err := db.Query("SELECT * FROM users LIMIT ? OFFSET ?", limit, offset)

批量操作

// 批量插入 func batchInsert(db *sql.DB, users []User) error { tx, err := db.Begin() if err != nil { return err } stmt, err := tx.Prepare("INSERT INTO users (name, age) VALUES (?, ?)") if err != nil { return err } defer stmt.Close() for _, user := range users { _, err = stmt.Exec(user.Name, user.Age) if err != nil { tx.Rollback() return err } } return tx.Commit() }

九、总结

Go语言的数据库操作通过database/sql包提供了统一的接口,结合ORM框架可以大大提高开发效率。以下是关键要点:

  1. 数据库连接:使用sql.Open创建连接,配置连接池参数
  2. CRUD操作:使用参数化查询防止SQL注入
  3. ORM框架:GORM提供便捷的数据访问层
  4. 事务处理:使用db.Begin()开启事务
  5. 数据库迁移:使用go-migrate管理schema变更
  6. 性能优化:索引优化、批量操作、查询优化

合理使用数据库操作可以显著提升应用的性能和可靠性。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询