面试题答案
一键面试设计思路
- 使用defer和recover:在每个goroutine中使用defer语句来确保无论是否发生异常,资源都能被正确释放。通过recover函数捕获异常,避免异常导致程序崩溃。
- 资源管理:对于共享资源(如文件描述符、数据库连接),可以封装在一个结构体中,在结构体的方法中进行资源的获取和释放操作。
- 同步机制:使用
sync.Mutex
或sync.RWMutex
来保护对共享资源的访问,避免竞态条件。
关键代码示例
package main
import (
"fmt"
"sync"
)
// 假设这是一个共享资源,例如数据库连接
type DatabaseConnection struct {
// 实际连接相关的字段
connection string
mu sync.Mutex
}
// 获取连接
func (db *DatabaseConnection) GetConnection() string {
db.mu.Lock()
defer db.mu.Unlock()
// 实际获取连接的逻辑
return "connection string"
}
// 释放连接
func (db *DatabaseConnection) ReleaseConnection() {
db.mu.Lock()
defer db.mu.Unlock()
// 实际释放连接的逻辑
fmt.Println("Connection released")
}
func worker(db *DatabaseConnection, wg *sync.WaitGroup) {
defer wg.Done()
// 获取资源
conn := db.GetConnection()
defer db.ReleaseConnection()
// 模拟可能发生异常的操作
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
}
}()
// 模拟异常
panic("Some error occurred")
fmt.Println("Using connection:", conn)
}
func main() {
var wg sync.WaitGroup
db := DatabaseConnection{}
// 启动多个goroutine
for i := 0; i < 3; i++ {
wg.Add(1)
go worker(&db, &wg)
}
wg.Wait()
fmt.Println("All workers completed")
}
在上述代码中:
DatabaseConnection
结构体封装了共享资源(数据库连接)以及用于保护资源访问的sync.Mutex
。worker
函数是每个goroutine执行的逻辑,通过defer
确保在函数结束时释放资源,无论是否发生异常。recover
函数捕获可能发生的异常,避免程序崩溃。