面试题答案
一键面试package main
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
func complexDBOperations() {
// 连接数据库
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/test")
if err != nil {
panic(err.Error())
}
defer func() {
// 无论函数如何结束,都会关闭数据库连接
err := db.Close()
if err != nil {
fmt.Println("Error closing database:", err)
}
}()
// 确保数据库可连接
err = db.Ping()
if err != nil {
fmt.Println("Failed to ping database:", err)
return
}
// 查询数据
rows, err := db.Query("SELECT * FROM some_table")
if err != nil {
fmt.Println("Error querying data:", err)
return
}
defer func() {
// 无论查询操作是否成功,都会关闭查询结果集
err := rows.Close()
if err != nil {
fmt.Println("Error closing rows:", err)
}
}()
// 处理查询结果
for rows.Next() {
// 具体处理逻辑
}
if err := rows.Err(); err != nil {
fmt.Println("Error iterating over rows:", err)
return
}
// 插入数据
result, err := db.Exec("INSERT INTO some_table (column1, column2) VALUES (?,?)", "value1", "value2")
if err != nil {
fmt.Println("Error inserting data:", err)
return
}
// 这里也可以根据result做一些操作,例如获取插入的ID
// 更新数据
result, err = db.Exec("UPDATE some_table SET column1 =? WHERE column2 =?", "new_value", "value2")
if err != nil {
fmt.Println("Error updating data:", err)
return
}
// 这里也可以根据result做一些操作,例如获取更新的行数
}
defer语句的作用和执行顺序:
-
数据库连接关闭的defer:
- 作用:确保在函数结束时,无论函数是正常结束还是因错误提前返回,数据库连接都会被关闭。这避免了资源泄露,因为数据库连接是有限资源。
- 执行顺序:在函数返回或结束时执行。如果函数正常结束,在所有其他语句执行完毕后执行;如果函数因错误提前返回,在错误处理逻辑执行完毕后执行。
-
查询结果集关闭的defer:
- 作用:确保在查询操作完成后,查询结果集(
rows
)会被关闭。这释放了与结果集相关的资源,避免资源泄露。 - 执行顺序:在查询相关操作完成后,当函数返回或结束时执行。例如,如果在处理查询结果过程中出现错误并提前返回,在错误处理逻辑执行完毕后,这个defer语句会关闭结果集。
- 作用:确保在查询操作完成后,查询结果集(