以下是一些Golang错误处理技巧及其示例代码:
- 返回错误值而不是panic:
func divide(a, b float64) (float64, error) {
if b == 0 {
return 0, errors.New("division by zero")
}
return a / b, nil
}
result, err := divide(10, 0)
if err != nil {
// 处理错误
}
- 使用defer函数进行错误处理:
func processFile(filename string) error {
file, err := os.Open(filename)
if err != nil {
return err
}
defer file.Close() // 确保文件被关闭
// 处理文件内容
// ...
return nil
}
- 使用错误链:
func main() {
err := doSomething()
if err != nil {
log.Printf("Error: %v", err)
if cause := errors.Cause(err); cause != nil {
log.Printf("Cause: %v", cause)
}
}
}
func doSomething() error {
err := doSomethingElse()
if err != nil {
return errors.Wrap(err, "failed to do something")
}
return nil
}
func doSomethingElse() error {
return errors.New("something went wrong")
}
- 使用标准库的错误处理功能:
func main() {
err := fmt.Errorf("an error occurred: %w", someOtherError)
if err != nil {
log.Printf("Error: %v", err)
if cause := errors.Unwrap(err); cause != nil {
log.Printf("Cause: %v", cause)
}
}
}
func someFunction() error {
return errors.New("something went wrong")
}
- 使用第三方库的错误处理功能:
func main() {
_, err := http.Get("https://www.example.com")
if err != nil {
log.Printf("Error: %v", err)
if urlError, ok := err.(*url.Error); ok {
log.Printf("Op: %v", urlError.Op)
log.Printf("URL: %v", urlError.URL)
}
}
}
- 在函数中添加注释:在编写代码时,应该将函数中可能返回的错误和其原因进行注释。这可以帮助调用者更好地理解函数并正确处理错误。
// connectToDatabase connects to a database and returns a connection object.
// If the connection fails, an error is returned.
func connectToDatabase() (*sql.DB, error) {
// ...
if err != nil {
return nil, fmt.Errorf("could not connect to database: %w", err)
}
// ...
}
- 在日志中包含足够的信息:当记录错误日志时,应该包含足够的信息以便后续的调试和问题诊断。这可以通过记录错误消息、堆栈跟踪和其他相关信息来实现。
func main() {
err := doSomething()
if err != nil {
log.Printf("Error: %v\nStack Trace: %s", err, debug.Stack())
}
}
func doSomething() error {
// ...
}
- 在测试中包含错误处理:在编写测试代码时,应该考虑测试错误处理和异常情况。这可以通过测试错误返回和错误处理代码路径来实现。
func TestDoSomething(t *testing.T) {
err := doSomething()
if err == nil {
t.Error("expected an error, but got nil")
}
expected := "something went wrong"
if err.Error() != expected {
t.Errorf("expected error message %q, but got %q", expected, err.Error())
}
}
func doSomething() error {
return errors.New("something went wrong")
}