面试题答案
一键面试匿名函数性能优化
- 内存管理
- 复用对象:避免在匿名函数内部频繁创建相同类型的对象。例如,如果匿名函数需要使用一个缓冲区,在外部创建并传递进来,而不是每次调用匿名函数都创建新的。
package main import ( "fmt" ) func main() { buffer := make([]byte, 1024) work := func() { // 使用外部传递进来的buffer,而不是在内部创建 fmt.Println(len(buffer)) } work() }
- 及时释放资源:对于持有资源(如文件句柄、数据库连接等)的匿名函数,确保在函数结束时及时关闭资源。在Go语言中,可以使用
defer
关键字。
package main import ( "fmt" "os" ) func main() { file, err := os.Open("test.txt") if err!= nil { fmt.Println(err) return } defer file.Close() processFile := func() { // 处理文件内容 data := make([]byte, 1024) n, err := file.Read(data) if err!= nil { fmt.Println(err) return } fmt.Println(string(data[:n])) } processFile() }
- 资源复用
- 使用sync.Pool:对于频繁创建和销毁的对象,可以使用
sync.Pool
来复用对象。例如,在处理HTTP请求的匿名函数中复用字节切片。
package main import ( "fmt" "sync" ) var bytePool = sync.Pool{ New: func() interface{} { return make([]byte, 1024) }, } func main() { handleRequest := func() { data := bytePool.Get().([]byte) defer bytePool.Put(data) // 使用data处理请求 fmt.Println(len(data)) } handleRequest() }
- 使用sync.Pool:对于频繁创建和销毁的对象,可以使用
常见陷阱及避免方法
- 资源泄漏
- 问题描述:如果在匿名函数中打开了资源(如文件、数据库连接等),但没有正确关闭,就会导致资源泄漏。
- 避免方法:如前面提到的,使用
defer
关键字确保资源在函数结束时关闭。
package main import ( "fmt" "os" ) func main() { file, err := os.Open("test.txt") if err!= nil { fmt.Println(err) return } defer file.Close() readFile := func() { defer func() { if r := recover(); r!= nil { fmt.Println("Recovered from panic:", r) file.Close() } }() // 可能导致panic的操作 panic("simulated panic") } readFile() }
- 竞态条件
- 问题描述:当多个goroutine同时访问和修改共享资源时,可能会出现竞态条件,导致数据不一致。
- 避免方法:
- 使用互斥锁(sync.Mutex):对共享资源的访问进行同步。
package main import ( "fmt" "sync" ) var ( counter int mutex sync.Mutex ) func main() { var wg sync.WaitGroup for i := 0; i < 10; i++ { wg.Add(1) go func() { defer wg.Done() mutex.Lock() counter++ mutex.Unlock() }() } wg.Wait() fmt.Println("Final counter:", counter) }
- 使用通道(channel):通过通道在goroutine之间传递数据,避免直接共享资源。
package main import ( "fmt" ) func main() { ch := make(chan int) var sum int for i := 0; i < 10; i++ { go func(n int) { ch <- n }(i) } for i := 0; i < 10; i++ { sum += <-ch } close(ch) fmt.Println("Sum:", sum) }