通过前几篇想必你已经知道该如何使用Go语言写一些简单的程序了,那么从这一篇开始,我们开始探究如何用go语言能够写真正的企业级应用。第一步我们实现先能让程序对数据库进行增删改查,这里以MySQL为例。
1. 导入必要的包
首先需要导入database/sql
包用于数据库操作的通用接口,以及特定数据库(MySQL)的驱动包(github.com/go-sql-driver/mysql
)。
import ("database/sql""fmt"_ "github.com/go-sql-driver/mysql"
)
2. 连接数据库
使用sql.Open()
函数来建立与MySQL数据库的连接。
func main() {db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/your_database?charset=utf8mb4&parseTime=True&loc=Local")if err!= nil {fmt.Println("数据库连接失败:", err)return}defer db.Close()// 测试连接是否成功err = db.Ping()if err!= nil {fmt.Println("数据库连接不可用:", err)return}fmt.Println("数据库连接成功")
}
3. 数据查询(SELECT)
- 基本查询
使用db.Query()
或db.QueryRow()
函数执行查询语句。Query
用于返回多行结果集,QueryRow
用于返回单行结果。问号代表的是预编译参数,如果你用过Java的JDBC,对此一定不会陌生。var id int var name string row := db.QueryRow("SELECT id, name FROM users WHERE id =?", 1) err = row.Scan(&id, &name) if err!= nil {fmt.Println("查询失败:", err)return } fmt.Printf("查询结果: id = %d, name = %s\n", id, name)
- 查询多行数据
使用db.Query()
结合rows.Next()
、rows.Scan()
来遍历结果集。rows, err := db.Query("SELECT id, name FROM users") if err!= nil {fmt.Println("查询失败:", err)return } defer rows.Close() for rows.Next() {var id intvar name stringerr = rows.Scan(&id, &name)if err!= nil {fmt.Println("扫描结果失败:", err)return}fmt.Printf("查询结果: id = %d, name = %s\n", id, name) } err = rows.Err() if err!= nil {fmt.Println("遍历结果集时出错:", err)return }
4. 数据插入(INSERT)
使用db.Exec()
函数执行插入语句。
result, err := db.Exec("INSERT INTO users (name, age) VALUES (?,?)", "张三", 30)
if err!= nil {fmt.Println("插入数据失败:", err)return
}
lastInsertId, err := result.LastInsertId()
if err!= nil {fmt.Println("获取插入ID失败:", err)return
}
fmt.Printf("插入成功,最后插入的ID为: %d\n", lastInsertId)
5. 数据更新(UPDATE)
同样使用db.Exec()
函数执行更新语句。
result, err := db.Exec("UPDATE users SET age =? WHERE name =?", 31, "张三")
if err!= nil {fmt.Println("更新数据失败:", err)return
}
rowsAffected, err := result.RowsAffected()
if err!= nil {fmt.Println("获取更新行数失败:", err)return
}
fmt.Printf("更新成功,影响的行数为: %d\n", rowsAffected)
6. 数据删除(DELETE)
使用db.Exec()
函数执行删除语句。
result, err := db.Exec("DELETE FROM users WHERE name =?", "张三")
if err!= nil {fmt.Println("删除数据失败:", err)return
}
rowsAffected, err := result.RowsAffected()
if err!= nil {fmt.Println("获取删除行数失败:", err)return
}
fmt.Printf("删除成功,影响的行数为: %d\n", rowsAffected)
7. 事务控制
在Go语言中,事务控制可以通过Tx
对象来实现。事务可以确保一组数据库操作要么全部成功,要么全部失败。
tx, err :=db.Begin()
if err != nil {fmt.Println("启动事务失败:", err)return
}_, err = tx.Exec("UPDATE users SET age = age + 1 WHERE id = 1")
if err != nil {fmt.Println("更新数据1失败:", err)return
}
fmt.Println("已更新数据1")
_, err = tx.Exec("UPDATE users SET age = age - 1 WHERE id = 2")
if err != nil {fmt.Println("更新数据2失败:", err)return
}
fmt.Println("已更新数据2")
tx.Rollback()
fmt.Println("已完成回滚")
_, err = tx.Exec("UPDATE users SET age = 30 WHERE id = 3")
if err != nil {fmt.Println("更新数据3失败:", err)return
}
fmt.Println("已更新数据3")
tx.Commit()
fmt.Println("已提交")
8. 数据库连接池设置
Go语言的database/sql
包提供了连接池的默认实现,但你可以通过设置连接池的参数来优化性能。
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/your_database?charset=utf8mb4&parseTime=True&loc=Local")
if err!= nil {fmt.Println("数据库连接失败:", err)return
}
defer db.Close()
// 设置连接池参数
db.SetMaxOpenConns(25) // 最大打开连接数
db.SetMaxIdleConns(25) // 最大空闲连接数
db.SetConnMaxLifetime(5 * time.Minute) // 连接最大生命周期
5. 总结
- 增删改查:使用
Exec
和Query
方法进行数据库操作。 - 事务控制:使用
Begin
、Commit
和Rollback
方法来管理事务。 - 并发控制:通过连接池管理和事务隔离级别来控制并发访问。
- 数据库连接池设置:通过
SetMaxOpenConns
、SetMaxIdleConns
和SetConnMaxLifetime
方法来配置连接池参数。