# Golang 数据库操作 ## 问题 1. Go 如何连接 MySQL 数据库? 2. database/sql 的使用方法是什么? 3. 如何使用 ORM(如 GORM)? 4. 如何处理数据库事务? 5. 如何处理 SQL 注入? --- ## 标准答案 ### 1. 连接 MySQL #### **使用 database/sql** ```go import ( "database/sql" _ "github.com/go-sql-driver/mysql" ) func main() { // 连接数据库 dsn := "user:password@tcp(127.0.0.1:3306)/dbname?parseTime=true" db, err := sql.Open("mysql", dsn) if err != nil { panic(err) } defer db.Close() // 测试连接 err = db.Ping() if err != nil { panic(err) } fmt.Println("Connected!") } ``` --- ### 2. database/sql 使用 #### **查询** ```go func queryUser(db *sql.DB, id int) (string, error) { var name string err := db.QueryRow("SELECT name FROM users WHERE id = ?", id).Scan(&name) if err != nil { return "", err } return name, nil } ``` --- #### **查询多行** ```go func queryUsers(db *sql.DB) ([]string, error) { rows, err := db.Query("SELECT name FROM users WHERE age > ?", 18) if err != nil { return nil, err } defer rows.Close() var names []string for rows.Next() { var name string if err := rows.Scan(&name); err != nil { return nil, err } names = append(names, name) } return names, nil } ``` --- ### 3. 使用 GORM #### **安装** ```bash go get -u gorm.io/gorm go get -u gorm.io/driver/mysql ``` --- #### **基本使用** ```go import ( "gorm.io/driver/mysql" "gorm.io/gorm" ) type User struct { ID uint `gorm:"primaryKey"` Name string `gorm:"column:name"` Age int `gorm:"column:age"` } func main() { // 连接数据库 dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) if err != nil { panic(err) } defer db.Close() // 自动迁移 db.AutoMigrate(&User{}) // 创建 user := User{Name: "Alice", Age: 25} db.Create(&user) // 查询 var users []User db.Where("age > ?", 18).Find(&users) } ``` --- ### 4. 事务处理 #### **database/sql 事务** ```go func transfer(db *sql.DB, from, to int, amount int) error { tx, err := db.Begin() if err != nil { return err } defer func() { if err != nil { tx.Rollback() } else { tx.Commit() } }() // 1. 扣款 _, err = tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from) if err != nil { return err } // 2. 存款 _, err = tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to) if err != nil { return err } return nil } ``` --- #### **GORM 事务** ```go func transfer(db *gorm.DB, from, to int, amount int) error { return db.Transaction(func(tx *gorm.DB) error { // 扣款 if err := tx.Exec("UPDATE accounts SET balance = balance - ? WHERE id = ?", amount, from).Error; err != nil { return err } // 存款 if err := tx.Exec("UPDATE accounts SET balance = balance + ? WHERE id = ?", amount, to).Error; err != nil { return err } return nil }) } ``` --- ### 5. SQL 注入防护 #### ✅ 使用参数化查询 ```go // ✅ 安全(参数化查询) db.Query("SELECT * FROM users WHERE id = ?", id) // ❌ 不安全(字符串拼接) db.Query(fmt.Sprintf("SELECT * FROM users WHERE id = %d", id)) ``` --- ### 6. 阿里 P7 加分项 **深度理解**: - 理解 database/sql 的连接池机制 - 理解 GORM 的底层实现(基于 database/sql) - 理解数据库事务的隔离级别 **实战经验**: - 有处理数据库连接池的经验 - 有优化数据库查询的经验(索引、批量操作) - 有处理分布式事务的经验 **性能优化**: - 理解如何优化数据库查询(预编译语句、批量操作) - 理解如何优化连接池配置 - 理解如何处理慢查询