面试题答案
一键面试可能原因
- 函数提前返回:如果在
defer
语句之前函数提前返回,可能由于异常或条件判断等原因,导致defer
语句中的文件关闭操作无法执行。例如:
package main
import (
"fmt"
"os"
)
func readFile() {
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("Open file error:", err)
// 这里没有关闭文件就返回了
return
}
defer file.Close()
// 后续读取文件操作
data := make([]byte, 1024)
n, err := file.Read(data)
if err != nil {
fmt.Println("Read file error:", err)
return
}
fmt.Println("Read data:", string(data[:n]))
}
在这个例子中,如果文件打开失败,函数直接返回,并没有关闭文件。
- 发生恐慌(panic):如果在
defer
语句之前发生panic
,并且没有合适的recover
来处理,程序会异常终止,defer
语句中的文件关闭操作可能无法正确执行。例如:
package main
import (
"fmt"
"os"
)
func readFile() {
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("Open file error:", err)
// 这里发生panic,defer语句在panic时会被执行,但如果panic没有被处理,程序还是异常终止
panic("File open failed")
}
defer file.Close()
// 后续读取文件操作
data := make([]byte, 1024)
n, err := file.Read(data)
if err != nil {
fmt.Println("Read file error:", err)
return
}
fmt.Println("Read data:", string(data[:n]))
}
这里发生panic
后,如果没有recover
处理,程序会异常终止,虽然defer
语句会被执行,但对整个程序稳定性有影响。
避免方法
- 处理错误并及时关闭文件:在打开文件后,立即检查错误并关闭文件。
package main
import (
"fmt"
"os"
)
func readFile() {
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("Open file error:", err)
return
}
defer file.Close()
// 后续读取文件操作
data := make([]byte, 1024)
n, err := file.Read(data)
if err != nil {
fmt.Println("Read file error:", err)
return
}
fmt.Println("Read data:", string(data[:n]))
}
- 使用
recover
处理panic
:如果函数可能发生panic
,可以使用recover
来捕获并处理,确保文件能正确关闭。
package main
import (
"fmt"
"os"
)
func readFile() {
file, err := os.Open("test.txt")
if err != nil {
fmt.Println("Open file error:", err)
return
}
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered from panic:", r)
file.Close()
}
}()
// 模拟可能发生panic的操作
panic("Simulated panic")
data := make([]byte, 1024)
n, err := file.Read(data)
if err != nil {
fmt.Println("Read file error:", err)
return
}
fmt.Println("Read data:", string(data[:n]))
}
这样在发生panic
时,recover
可以捕获并关闭文件,避免文件未关闭的问题。