面试题答案
一键面试- 错误类型定义:
- 在Go中,使用
error
接口来表示错误。对于项目特定的错误,定义专门的错误类型。例如,如果项目涉及数据库操作,可以定义:
type DatabaseError struct { ErrMsg string } func (de DatabaseError) Error() string { return de.ErrMsg }
- 这样做可以在不同模块中统一识别和处理特定类型的错误,便于调试。
- 在Go中,使用
- 模块间错误传递:
- 每个模块的函数在发生错误时,应尽可能简单直接地返回错误。例如:
func readFile(filePath string) ([]byte, error) { data, err := ioutil.ReadFile(filePath) if err != nil { return nil, err } return data, nil }
- 调用方模块接收错误后,可以决定如何处理。这样各模块只关注自身功能和错误产生,而不关心其他模块如何处理错误,保持低耦合。
- 错误日志记录:
- 使用日志库(如
log
包或更高级的zap
库)记录错误信息。在关键函数或模块入口、出口处记录错误,例如:
func main() { data, err := readFile("test.txt") if err != nil { log.Printf("Error reading file: %v", err) return } // 后续处理data }
- 详细的错误日志有助于在调试时快速定位问题。
- 使用日志库(如
- 错误包装(Go 1.13+):
- 使用
fmt.Errorf
的%w
动词进行错误包装。例如:
func processData(data []byte) error { if len(data) == 0 { return fmt.Errorf("data is empty: %w", ErrInvalidData) } // 处理数据 return nil }
- 调用方可以使用
errors.As
和errors.Is
函数来检查和处理包装的错误,这样既保留了原始错误信息,又能在不同层次传递更丰富的错误上下文。
- 使用
- 错误处理中间件(如果适用):
- 在一些框架(如HTTP服务器框架)中,可以使用中间件来统一处理错误。例如,在一个HTTP服务器项目中:
func errorHandler(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { defer func() { if err := recover(); err != nil { log.Printf("Panic: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) } }() next.ServeHTTP(w, r) }) }
- 这样可以在不侵入业务逻辑的情况下,对整个项目的错误进行统一处理,降低模块间耦合。