面试题答案
一键面试1. 优化思路
- 数据库连接池:减少每次数据库操作时建立新连接的开销,通过连接池复用已有连接。
- 预编译SQL语句:避免重复编译SQL语句,提高执行效率,同时防止SQL注入。
- 批量操作:在进行插入、更新等操作时,尽量采用批量方式,减少数据库交互次数。
2. 具体措施
- 连接池:使用
database/sql
包的sql.Open
和db.SetMaxIdleConns
、db.SetMaxOpenConns
方法来管理连接池。 - 预编译SQL:使用
db.Prepare
方法对SQL语句进行预编译,然后使用预编译的stmt
执行操作。 - 批量操作:在插入多条记录时,构建包含多个值的SQL语句,一次执行。
3. 生成代码示例
package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
// User 结构体对应 users 表
type User struct {
ID int
Name string
Age int
}
// GetDB 初始化数据库连接
func GetDB() (*sql.DB, error) {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/database_name")
if err != nil {
return nil, err
}
// 设置最大空闲连接数
db.SetMaxIdleConns(10)
// 设置最大打开连接数
db.SetMaxOpenConns(100)
return db, nil
}
// InsertUser 插入用户
func InsertUser(user User) (int64, error) {
db, err := GetDB()
if err != nil {
return 0, err
}
defer db.Close()
sqlStmt := `INSERT INTO users (name, age) VALUES (?,?)`
stmt, err := db.Prepare(sqlStmt)
if err != nil {
return 0, err
}
defer stmt.Close()
result, err := stmt.Exec(user.Name, user.Age)
if err != nil {
return 0, err
}
return result.LastInsertId()
}
// GetUser 获取用户
func GetUser(id int) (*User, error) {
db, err := GetDB()
if err != nil {
return nil, err
}
defer db.Close()
sqlStmt := `SELECT id, name, age FROM users WHERE id =?`
stmt, err := db.Prepare(sqlStmt)
if err != nil {
return nil, err
}
defer stmt.Close()
var user User
err = stmt.QueryRow(id).Scan(&user.ID, &user.Name, &user.Age)
if err != nil {
return nil, err
}
return &user, nil
}
// UpdateUser 更新用户
func UpdateUser(user User) (int64, error) {
db, err := GetDB()
if err != nil {
return 0, err
}
defer db.Close()
sqlStmt := `UPDATE users SET name =?, age =? WHERE id =?`
stmt, err := db.Prepare(sqlStmt)
if err != nil {
return 0, err
}
defer stmt.Close()
result, err := stmt.Exec(user.Name, user.Age, user.ID)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
// DeleteUser 删除用户
func DeleteUser(id int) (int64, error) {
db, err := GetDB()
if err != nil {
return 0, err
}
defer db.Close()
sqlStmt := `DELETE FROM users WHERE id =?`
stmt, err := db.Prepare(sqlStmt)
if err != nil {
return 0, err
}
defer stmt.Close()
result, err := stmt.Exec(id)
if err != nil {
return 0, err
}
return result.RowsAffected()
}
4. 代码说明
- 结构体定义:
User
结构体对应数据库中的users
表结构。 - 数据库连接:
GetDB
函数初始化数据库连接,并设置连接池参数。 - 增删改查方法:
InsertUser
:使用预编译SQL插入用户数据。GetUser
:通过预编译SQL查询单个用户。UpdateUser
:预编译SQL更新用户信息。DeleteUser
:预编译SQL删除用户。
上述代码以MySQL为例,实际使用时需根据具体数据库类型调整驱动和连接字符串。