Go错误处理策略 - Golang企业级错误管理最佳实践
错误处理是Go语言的核心特性之一,良好的错误处理策略能够提高系统的健壮性、可维护性和用户体验。在企业级应用中,需要建立完善的错误管理体系。
📋 重点面试题
面试题 1:Go应用的企业级错误处理体系设计
难度级别:⭐⭐⭐⭐⭐
考察范围:错误处理/系统设计
技术标签:error handling system reliability error management fault tolerance
详细解答
1. 错误处理体系架构
点击查看完整代码实现
点击查看完整代码实现
go
package main
import (
"context"
"fmt"
"log"
"runtime"
"strconv"
"strings"
"sync"
"time"
)
func demonstrateErrorHandlingStrategy() {
fmt.Println("=== Go错误处理策略 ===")
/*
错误处理策略核心要素:
1. 错误分类体系:
- 业务错误:用户输入错误、权限错误等
- 系统错误:网络错误、数据库错误等
- 致命错误:内存不足、配置错误等
- 临时错误:超时、限流等可重试错误
2. 错误信息设计:
- 错误码:唯一标识错误类型
- 错误消息:用户友好的描述
- 技术细节:开发者需要的详细信息
- 上下文信息:请求ID、用户ID等
3. 错误处理策略:
- 快速失败:立即返回错误
- 重试机制:自动重试临时错误
- 降级处理:提供替代方案
- 熔断保护:防止错误传播
4. 错误监控告警:
- 错误统计:错误率、错误分布
- 异常检测:异常模式识别
- 告警机制:及时通知相关人员
- 错误追踪:完整的错误链路
*/
demonstrateErrorClassification()
demonstrateCustomErrors()
demonstrateErrorPropagation()
demonstrateErrorRecovery()
}
func demonstrateErrorClassification() {
fmt.Println("\n--- 错误分类体系 ---")
/*
错误分类要点:
1. 按错误性质分类:业务、系统、配置
2. 按严重程度分类:致命、错误、警告
3. 按处理方式分类:可重试、不可重试
4. 按影响范围分类:用户级、服务级、系统级
*/
// 错误类型定义
type ErrorType int
const (
ErrorTypeBusiness ErrorType = iota // 业务错误
ErrorTypeSystem // 系统错误
ErrorTypeNetwork // 网络错误
ErrorTypeValidation // 验证错误
ErrorTypePermission // 权限错误
ErrorTypeConfiguration // 配置错误
ErrorTypeTimeout // 超时错误
ErrorTypeResource // 资源错误
)
func (et ErrorType) String() string {
switch et {
case ErrorTypeBusiness:
return "BUSINESS"
case ErrorTypeSystem:
return "SYSTEM"
case ErrorTypeNetwork:
return "NETWORK"
case ErrorTypeValidation:
return "VALIDATION"
case ErrorTypePermission:
return "PERMISSION"
case ErrorTypeConfiguration:
return "CONFIGURATION"
case ErrorTypeTimeout:
return "TIMEOUT"
case ErrorTypeResource:
return "RESOURCE"
default:
return "UNKNOWN"
}
}
// 错误严重级别
type ErrorSeverity int
const (
SeverityLow ErrorSeverity = iota
SeverityMedium
SeverityHigh
SeverityCritical
)
func (es ErrorSeverity) String() string {
switch es {
case SeverityLow:
return "LOW"
case SeverityMedium:
return "MEDIUM"
case SeverityHigh:
return "HIGH"
case SeverityCritical:
return "CRITICAL"
default:
return "UNKNOWN"
}
}
// 分类错误接口
type ClassifiedError interface {
error
Code() string
Type() ErrorType
Severity() ErrorSeverity
IsRetryable() bool
IsTemporary() bool
Details() map[string]interface{}
StackTrace() string
}
// 基础分类错误实现
type BaseClassifiedError struct {
code string
message string
errorType ErrorType
severity ErrorSeverity
retryable bool
temporary bool
details map[string]interface{}
stackTrace string
cause error
}
func NewClassifiedError(code, message string, errorType ErrorType, severity ErrorSeverity) *BaseClassifiedError {
return &BaseClassifiedError{
code: code,
message: message,
errorType: errorType,
severity: severity,
retryable: false,
temporary: false,
details: make(map[string]interface{}),
stackTrace: captureStackTrace(),
}
}
func (bce *BaseClassifiedError) Error() string {
return fmt.Sprintf("[%s] %s: %s", bce.code, bce.errorType.String(), bce.message)
}
func (bce *BaseClassifiedError) Code() string {
return bce.code
}
func (bce *BaseClassifiedError) Type() ErrorType {
return bce.errorType
}
func (bce *BaseClassifiedError) Severity() ErrorSeverity {
return bce.severity
}
func (bce *BaseClassifiedError) IsRetryable() bool {
return bce.retryable
}
func (bce *BaseClassifiedError) IsTemporary() bool {
return bce.temporary
}
func (bce *BaseClassifiedError) Details() map[string]interface{} {
return bce.details
}
func (bce *BaseClassifiedError) StackTrace() string {
return bce.stackTrace
}
func (bce *BaseClassifiedError) WithCause(cause error) *BaseClassifiedError {
bce.cause = cause
return bce
}
func (bce *BaseClassifiedError) WithDetail(key string, value interface{}) *BaseClassifiedError {
bce.details[key] = value
return bce
}
func (bce *BaseClassifiedError) SetRetryable(retryable bool) *BaseClassifiedError {
bce.retryable = retryable
return bce
}
func (bce *BaseClassifiedError) SetTemporary(temporary bool) *BaseClassifiedError {
bce.temporary = temporary
return bce
}
func captureStackTrace() string {
var buf strings.Builder
for i := 2; i < 10; i++ { // 跳过当前函数和调用者
pc, file, line, ok := runtime.Caller(i)
if !ok {
break
}
fn := runtime.FuncForPC(pc)
if fn == nil {
continue
}
funcName := fn.Name()
if idx := strings.LastIndex(funcName, "/"); idx != -1 {
funcName = funcName[idx+1:]
}
if idx := strings.LastIndex(file, "/"); idx != -1 {
file = file[idx+1:]
}
buf.WriteString(fmt.Sprintf(" %s:%d %s\n", file, line, funcName))
}
return buf.String()
}
// 具体错误类型工厂
type ErrorFactory struct{}
func (ef *ErrorFactory) NewValidationError(message string) *BaseClassifiedError {
return NewClassifiedError("VALIDATION_001", message, ErrorTypeValidation, SeverityMedium)
}
func (ef *ErrorFactory) NewPermissionError(message string) *BaseClassifiedError {
return NewClassifiedError("PERMISSION_001", message, ErrorTypePermission, SeverityHigh)
}
func (ef *ErrorFactory) NewNetworkError(message string) *BaseClassifiedError {
return NewClassifiedError("NETWORK_001", message, ErrorTypeNetwork, SeverityMedium).
SetRetryable(true).
SetTemporary(true)
}
func (ef *ErrorFactory) NewDatabaseError(message string) *BaseClassifiedError {
return NewClassifiedError("DATABASE_001", message, ErrorTypeSystem, SeverityHigh).
SetRetryable(true)
}
func (ef *ErrorFactory) NewTimeoutError(message string) *BaseClassifiedError {
return NewClassifiedError("TIMEOUT_001", message, ErrorTypeTimeout, SeverityMedium).
SetRetryable(true).
SetTemporary(true)
}
func (ef *ErrorFactory) NewBusinessError(code, message string) *BaseClassifiedError {
return NewClassifiedError(code, message, ErrorTypeBusiness, SeverityLow)
}
// 演示错误分类
fmt.Printf("错误分类体系演示:\n")
factory := &ErrorFactory{}
// 创建不同类型的错误
errors := []ClassifiedError{
factory.NewValidationError("用户名不能为空"),
factory.NewPermissionError("权限不足,无法访问该资源"),
factory.NewNetworkError("网络连接超时").WithDetail("timeout", "5s"),
factory.NewDatabaseError("数据库连接失败").WithDetail("host", "localhost:5432"),
factory.NewTimeoutError("请求处理超时").WithDetail("duration", "30s"),
factory.NewBusinessError("ORDER_001", "订单状态不允许取消"),
}
fmt.Printf(" 📊 错误分类统计:\n")
typeCount := make(map[ErrorType]int)
severityCount := make(map[ErrorSeverity]int)
retryableCount := 0
temporaryCount := 0
for i, err := range errors {
fmt.Printf(" %d. %s\n", i+1, err.Error())
fmt.Printf(" 类型: %s, 严重程度: %s\n", err.Type().String(), err.Severity().String())
fmt.Printf(" 可重试: %t, 临时性: %t\n", err.IsRetryable(), err.IsTemporary())
if len(err.Details()) > 0 {
fmt.Printf(" 详细信息: %v\n", err.Details())
}
// 统计
typeCount[err.Type()]++
severityCount[err.Severity()]++
if err.IsRetryable() {
retryableCount++
}
if err.IsTemporary() {
temporaryCount++
}
fmt.Println()
}
fmt.Printf(" 📈 统计摘要:\n")
fmt.Printf(" 按类型分布:\n")
for errorType, count := range typeCount {
fmt.Printf(" %s: %d\n", errorType.String(), count)
}
fmt.Printf(" 按严重程度分布:\n")
for severity, count := range severityCount {
fmt.Printf(" %s: %d\n", severity.String(), count)
}
fmt.Printf(" 可重试错误: %d/%d\n", retryableCount, len(errors))
fmt.Printf(" 临时性错误: %d/%d\n", temporaryCount, len(errors))
}
func demonstrateCustomErrors() {
fmt.Println("\n--- 自定义错误设计 ---")
/*
自定义错误要点:
1. 错误包装:保留原始错误信息
2. 上下文传递:携带请求上下文
3. 错误链:构建错误调用链
4. 元数据:附加诊断信息
*/
// 上下文错误
type ContextualError struct {
BaseError error
Context context.Context
RequestID string
UserID string
Operation string
Timestamp time.Time
AdditionalInfo map[string]interface{}
}
func NewContextualError(ctx context.Context, operation string, baseError error) *ContextualError {
ce := &ContextualError{
BaseError: baseError,
Context: ctx,
Operation: operation,
Timestamp: time.Now(),
AdditionalInfo: make(map[string]interface{}),
}
// 从上下文中提取信息
if requestID := ctx.Value("request_id"); requestID != nil {
if id, ok := requestID.(string); ok {
ce.RequestID = id
}
}
if userID := ctx.Value("user_id"); userID != nil {
if id, ok := userID.(string); ok {
ce.UserID = id
}
}
return ce
}
func (ce *ContextualError) Error() string {
return fmt.Sprintf("[%s] %s: %v", ce.Operation, ce.RequestID, ce.BaseError)
}
func (ce *ContextualError) Unwrap() error {
return ce.BaseError
}
func (ce *ContextualError) WithInfo(key string, value interface{}) *ContextualError {
ce.AdditionalInfo[key] = value
return ce
}
// 错误链构建器
type ErrorChain struct {
errors []error
mutex sync.RWMutex
}
func NewErrorChain() *ErrorChain {
return &ErrorChain{
errors: make([]error, 0),
}
}
func (ec *ErrorChain) Add(err error) *ErrorChain {
if err == nil {
return ec
}
ec.mutex.Lock()
defer ec.mutex.Unlock()
ec.errors = append(ec.errors, err)
return ec
}
func (ec *ErrorChain) HasErrors() bool {
ec.mutex.RLock()
defer ec.mutex.RUnlock()
return len(ec.errors) > 0
}
func (ec *ErrorChain) Error() string {
ec.mutex.RLock()
defer ec.mutex.RUnlock()
if len(ec.errors) == 0 {
return "no errors"
}
if len(ec.errors) == 1 {
return ec.errors[0].Error()
}
var builder strings.Builder
builder.WriteString("multiple errors occurred:\n")
for i, err := range ec.errors {
builder.WriteString(fmt.Sprintf(" %d. %s\n", i+1, err.Error()))
}
return builder.String()
}
func (ec *ErrorChain) Errors() []error {
ec.mutex.RLock()
defer ec.mutex.RUnlock()
result := make([]error, len(ec.errors))
copy(result, ec.errors)
return result
}
func (ec *ErrorChain) First() error {
ec.mutex.RLock()
defer ec.mutex.RUnlock()
if len(ec.errors) > 0 {
return ec.errors[0]
}
return nil
}
func (ec *ErrorChain) Last() error {
ec.mutex.RLock()
defer ec.mutex.RUnlock()
if len(ec.errors) > 0 {
return ec.errors[len(ec.errors)-1]
}
return nil
}
// 业务错误包装器
type BusinessErrorWrapper struct {
UserMessage string // 用户友好的消息
TechnicalError error // 技术错误详情
ErrorCode string // 业务错误码
Suggestions []string // 解决建议
}
func NewBusinessErrorWrapper(code, userMessage string, technicalError error) *BusinessErrorWrapper {
return &BusinessErrorWrapper{
UserMessage: userMessage,
TechnicalError: technicalError,
ErrorCode: code,
Suggestions: make([]string, 0),
}
}
func (bew *BusinessErrorWrapper) Error() string {
return fmt.Sprintf("[%s] %s", bew.ErrorCode, bew.UserMessage)
}
func (bew *BusinessErrorWrapper) Unwrap() error {
return bew.TechnicalError
}
func (bew *BusinessErrorWrapper) AddSuggestion(suggestion string) *BusinessErrorWrapper {
bew.Suggestions = append(bew.Suggestions, suggestion)
return bew
}
func (bew *BusinessErrorWrapper) GetUserMessage() string {
return bew.UserMessage
}
func (bew *BusinessErrorWrapper) GetTechnicalDetails() string {
if bew.TechnicalError != nil {
return bew.TechnicalError.Error()
}
return ""
}
func (bew *BusinessErrorWrapper) GetSuggestions() []string {
return bew.Suggestions
}
// 演示自定义错误
fmt.Printf("自定义错误设计演示:\n")
// 模拟业务操作
simulateBusinessOperation := func() error {
// 创建带上下文的请求
ctx := context.Background()
ctx = context.WithValue(ctx, "request_id", "req-12345")
ctx = context.WithValue(ctx, "user_id", "user-67890")
// 模拟数据库错误
dbError := fmt.Errorf("connection timeout after 5s")
// 包装为上下文错误
contextError := NewContextualError(ctx, "user_lookup", dbError).
WithInfo("table", "users").
WithInfo("query_duration", "5.2s")
// 包装为业务错误
businessError := NewBusinessErrorWrapper(
"USER_LOOKUP_FAILED",
"用户信息获取失败,请稍后重试",
contextError,
).AddSuggestion("检查网络连接").
AddSuggestion("联系技术支持")
return businessError
}
// 模拟多个错误的聚合
simulateMultipleErrors := func() error {
chain := NewErrorChain()
// 模拟验证错误
chain.Add(fmt.Errorf("用户名不能为空"))
chain.Add(fmt.Errorf("密码长度不足8位"))
chain.Add(fmt.Errorf("邮箱格式不正确"))
if chain.HasErrors() {
return chain
}
return nil
}
fmt.Printf(" 🔍 上下文错误示例:\n")
if err := simulateBusinessOperation(); err != nil {
fmt.Printf(" 错误: %s\n", err.Error())
// 类型断言获取详细信息
if businessErr, ok := err.(*BusinessErrorWrapper); ok {
fmt.Printf(" 用户消息: %s\n", businessErr.GetUserMessage())
fmt.Printf(" 技术详情: %s\n", businessErr.GetTechnicalDetails())
fmt.Printf(" 解决建议: %v\n", businessErr.GetSuggestions())
// 解包获取原始错误
if contextErr, ok := businessErr.Unwrap().(*ContextualError); ok {
fmt.Printf(" 请求ID: %s\n", contextErr.RequestID)
fmt.Printf(" 用户ID: %s\n", contextErr.UserID)
fmt.Printf(" 操作: %s\n", contextErr.Operation)
fmt.Printf(" 时间戳: %s\n", contextErr.Timestamp.Format(time.RFC3339))
fmt.Printf(" 附加信息: %v\n", contextErr.AdditionalInfo)
}
}
}
fmt.Printf("\n 📝 错误链示例:\n")
if err := simulateMultipleErrors(); err != nil {
fmt.Printf(" %s", err.Error())
if errorChain, ok := err.(*ErrorChain); ok {
fmt.Printf(" 错误总数: %d\n", len(errorChain.Errors()))
fmt.Printf(" 首个错误: %s\n", errorChain.First().Error())
fmt.Printf(" 最后错误: %s\n", errorChain.Last().Error())
}
}
}
func demonstrateErrorPropagation() {
fmt.Println("\n--- 错误传播机制 ---")
/*
错误传播要点:
1. 错误包装:保留调用栈信息
2. 错误转换:适配不同层级的错误
3. 错误过滤:决定哪些错误需要传播
4. 错误增强:添加上下文信息
*/
// 错误传播器
type ErrorPropagator struct {
filters []ErrorFilter
transformers []ErrorTransformer
enhancers []ErrorEnhancer
}
type ErrorFilter interface {
ShouldPropagate(err error) bool
}
type ErrorTransformer interface {
Transform(err error) error
}
type ErrorEnhancer interface {
Enhance(err error, context map[string]interface{}) error
}
// 严重性过滤器
type SeverityFilter struct {
MinSeverity ErrorSeverity
}
func (sf *SeverityFilter) ShouldPropagate(err error) bool {
if classifiedErr, ok := err.(ClassifiedError); ok {
return classifiedErr.Severity() >= sf.MinSeverity
}
return true // 未分类错误默认传播
}
// 错误类型转换器
type ErrorTypeTransformer struct {
FromType ErrorType
ToType ErrorType
}
func (ett *ErrorTypeTransformer) Transform(err error) error {
if classifiedErr, ok := err.(*BaseClassifiedError); ok {
if classifiedErr.Type() == ett.FromType {
// 创建新的错误类型
newErr := NewClassifiedError(
classifiedErr.Code(),
classifiedErr.message,
ett.ToType,
classifiedErr.Severity(),
)
newErr.details = classifiedErr.details
return newErr
}
}
return err
}
// 上下文增强器
type ContextEnhancer struct {
Service string
Version string
}
func (ce *ContextEnhancer) Enhance(err error, context map[string]interface{}) error {
// 创建增强的错误包装
enhanced := &EnhancedError{
OriginalError: err,
Service: ce.Service,
Version: ce.Version,
Context: context,
Timestamp: time.Now(),
}
return enhanced
}
type EnhancedError struct {
OriginalError error
Service string
Version string
Context map[string]interface{}
Timestamp time.Time
}
func (ee *EnhancedError) Error() string {
return fmt.Sprintf("[%s@%s] %s", ee.Service, ee.Version, ee.OriginalError.Error())
}
func (ee *EnhancedError) Unwrap() error {
return ee.OriginalError
}
func NewErrorPropagator() *ErrorPropagator {
return &ErrorPropagator{
filters: make([]ErrorFilter, 0),
transformers: make([]ErrorTransformer, 0),
enhancers: make([]ErrorEnhancer, 0),
}
}
func (ep *ErrorPropagator) AddFilter(filter ErrorFilter) {
ep.filters = append(ep.filters, filter)
}
func (ep *ErrorPropagator) AddTransformer(transformer ErrorTransformer) {
ep.transformers = append(ep.transformers, transformer)
}
func (ep *ErrorPropagator) AddEnhancer(enhancer ErrorEnhancer) {
ep.enhancers = append(ep.enhancers, enhancer)
}
func (ep *ErrorPropagator) Propagate(err error, context map[string]interface{}) error {
if err == nil {
return nil
}
// 应用过滤器
for _, filter := range ep.filters {
if !filter.ShouldPropagate(err) {
return nil // 不传播此错误
}
}
// 应用转换器
for _, transformer := range ep.transformers {
err = transformer.Transform(err)
}
// 应用增强器
for _, enhancer := range ep.enhancers {
err = enhancer.Enhance(err, context)
}
return err
}
// 演示错误传播
fmt.Printf("错误传播机制演示:\n")
// 创建错误传播器
propagator := NewErrorPropagator()
// 添加严重性过滤器(只传播中等以上严重度的错误)
propagator.AddFilter(&SeverityFilter{MinSeverity: SeverityMedium})
// 添加错误类型转换器(将网络错误转换为系统错误)
propagator.AddTransformer(&ErrorTypeTransformer{
FromType: ErrorTypeNetwork,
ToType: ErrorTypeSystem,
})
// 添加上下文增强器
propagator.AddEnhancer(&ContextEnhancer{
Service: "user-service",
Version: "v1.2.3",
})
// 测试不同类型的错误传播
factory := &ErrorFactory{}
testErrors := []error{
factory.NewValidationError("输入验证失败"), // 中等严重度,应该传播
NewClassifiedError("TRACE_001", "调试信息", ErrorTypeBusiness, SeverityLow), // 低严重度,应该被过滤
factory.NewNetworkError("网络连接失败"), // 网络错误,应该被转换为系统错误
factory.NewDatabaseError("数据库查询失败"), // 高严重度,应该传播
}
context := map[string]interface{}{
"request_id": "req-98765",
"user_id": "user-12345",
"operation": "get_user_profile",
}
fmt.Printf(" 🚀 错误传播测试:\n")
for i, originalErr := range testErrors {
fmt.Printf(" 测试 %d - 原始错误: %s\n", i+1, originalErr.Error())
propagatedErr := propagator.Propagate(originalErr, context)
if propagatedErr == nil {
fmt.Printf(" 结果: 错误被过滤,未传播\n")
} else {
fmt.Printf(" 结果: %s\n", propagatedErr.Error())
// 检查是否被增强
if enhanced, ok := propagatedErr.(*EnhancedError); ok {
fmt.Printf(" 服务: %s\n", enhanced.Service)
fmt.Printf(" 版本: %s\n", enhanced.Version)
fmt.Printf(" 时间戳: %s\n", enhanced.Timestamp.Format("15:04:05"))
fmt.Printf(" 上下文: %v\n", enhanced.Context)
}
}
fmt.Println()
}
}
func demonstrateErrorRecovery() {
fmt.Println("\n--- 错误恢复策略 ---")
/*
错误恢复要点:
1. 重试机制:指数退避、最大重试次数
2. 熔断保护:防止级联失败
3. 降级处理:提供备用方案
4. 超时控制:避免无限等待
*/
// 重试策略
type RetryStrategy interface {
ShouldRetry(attempt int, err error) bool
NextDelay(attempt int) time.Duration
MaxAttempts() int
}
// 指数退避重试策略
type ExponentialBackoffStrategy struct {
InitialDelay time.Duration
MaxDelay time.Duration
Multiplier float64
MaxRetries int
}
func (ebs *ExponentialBackoffStrategy) ShouldRetry(attempt int, err error) bool {
if attempt >= ebs.MaxRetries {
return false
}
// 检查错误是否可重试
if classifiedErr, ok := err.(ClassifiedError); ok {
return classifiedErr.IsRetryable()
}
return false
}
func (ebs *ExponentialBackoffStrategy) NextDelay(attempt int) time.Duration {
delay := time.Duration(float64(ebs.InitialDelay) *
pow(ebs.Multiplier, float64(attempt)))
if delay > ebs.MaxDelay {
delay = ebs.MaxDelay
}
return delay
}
func (ebs *ExponentialBackoffStrategy) MaxAttempts() int {
return ebs.MaxRetries
}
// 简单的幂运算实现
func pow(base, exp float64) float64 {
if exp == 0 {
return 1
}
result := base
for i := 1; i < int(exp); i++ {
result *= base
}
return result
}
// 重试执行器
type RetryExecutor struct {
strategy RetryStrategy
logger *log.Logger
}
func NewRetryExecutor(strategy RetryStrategy) *RetryExecutor {
return &RetryExecutor{
strategy: strategy,
logger: log.New(log.Writer(), "[RETRY] ", log.LstdFlags),
}
}
func (re *RetryExecutor) Execute(ctx context.Context, operation func() error) error {
var lastErr error
for attempt := 0; attempt < re.strategy.MaxAttempts(); attempt++ {
// 检查上下文是否已取消
select {
case <-ctx.Done():
return ctx.Err()
default:
}
// 执行操作
err := operation()
if err == nil {
if attempt > 0 {
re.logger.Printf("操作在第 %d 次重试后成功", attempt+1)
}
return nil
}
lastErr = err
// 检查是否应该重试
if !re.strategy.ShouldRetry(attempt, err) {
re.logger.Printf("错误不可重试或达到最大重试次数: %v", err)
break
}
// 计算延迟时间
delay := re.strategy.NextDelay(attempt)
re.logger.Printf("第 %d 次重试失败: %v, %v 后重试", attempt+1, err, delay)
// 等待重试
select {
case <-ctx.Done():
return ctx.Err()
case <-time.After(delay):
// 继续重试
}
}
return fmt.Errorf("重试 %d 次后仍然失败: %v", re.strategy.MaxAttempts(), lastErr)
}
// 熔断器(简化版)
type CircuitBreaker struct {
name string
maxFailures int
resetTimeout time.Duration
failures int
lastFailTime time.Time
state string
mutex sync.RWMutex
}
func NewCircuitBreaker(name string, maxFailures int, resetTimeout time.Duration) *CircuitBreaker {
return &CircuitBreaker{
name: name,
maxFailures: maxFailures,
resetTimeout: resetTimeout,
state: "CLOSED",
}
}
func (cb *CircuitBreaker) Execute(operation func() error) error {
cb.mutex.RLock()
state := cb.state
failures := cb.failures
lastFailTime := cb.lastFailTime
cb.mutex.RUnlock()
// 检查熔断器状态
if state == "OPEN" {
if time.Since(lastFailTime) > cb.resetTimeout {
cb.mutex.Lock()
cb.state = "HALF_OPEN"
cb.mutex.Unlock()
} else {
return fmt.Errorf("熔断器 %s 已开启", cb.name)
}
}
// 执行操作
err := operation()
cb.mutex.Lock()
defer cb.mutex.Unlock()
if err != nil {
cb.failures++
cb.lastFailTime = time.Now()
if cb.failures >= cb.maxFailures {
cb.state = "OPEN"
log.Printf("熔断器 %s 开启,失败次数: %d", cb.name, cb.failures)
}
return err
}
// 成功时重置
if cb.state == "HALF_OPEN" {
cb.state = "CLOSED"
log.Printf("熔断器 %s 恢复正常", cb.name)
}
cb.failures = 0
return nil
}
// 降级处理器
type FallbackHandler struct {
primary func() (interface{}, error)
fallback func() (interface{}, error)
threshold time.Duration
}
func NewFallbackHandler(primary, fallback func() (interface{}, error), threshold time.Duration) *FallbackHandler {
return &FallbackHandler{
primary: primary,
fallback: fallback,
threshold: threshold,
}
}
func (fh *FallbackHandler) Execute() (interface{}, error) {
// 设置超时
ctx, cancel := context.WithTimeout(context.Background(), fh.threshold)
defer cancel()
resultCh := make(chan interface{}, 1)
errorCh := make(chan error, 1)
// 执行主要操作
go func() {
result, err := fh.primary()
if err != nil {
errorCh <- err
} else {
resultCh <- result
}
}()
select {
case result := <-resultCh:
return result, nil
case err := <-errorCh:
log.Printf("主要操作失败,执行降级: %v", err)
return fh.fallback()
case <-ctx.Done():
log.Printf("主要操作超时,执行降级")
return fh.fallback()
}
}
// 演示错误恢复
fmt.Printf("错误恢复策略演示:\n")
// 1. 重试机制演示
fmt.Printf(" 🔄 重试机制测试:\n")
retryStrategy := &ExponentialBackoffStrategy{
InitialDelay: 100 * time.Millisecond,
MaxDelay: 1 * time.Second,
Multiplier: 2.0,
MaxRetries: 3,
}
executor := NewRetryExecutor(retryStrategy)
// 模拟不稳定的操作
callCount := 0
unstableOperation := func() error {
callCount++
if callCount < 3 { // 前两次失败
factory := &ErrorFactory{}
return factory.NewNetworkError(fmt.Sprintf("网络错误 #%d", callCount))
}
return nil // 第三次成功
}
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
if err := executor.Execute(ctx, unstableOperation); err != nil {
fmt.Printf(" ❌ 重试失败: %v\n", err)
} else {
fmt.Printf(" ✅ 重试成功,总调用次数: %d\n", callCount)
}
// 2. 熔断器演示
fmt.Printf("\n ⚡ 熔断器测试:\n")
breaker := NewCircuitBreaker("test-service", 2, 2*time.Second)
// 模拟失败操作
failingOperation := func() error {
return fmt.Errorf("服务不可用")
}
// 连续失败触发熔断
for i := 1; i <= 5; i++ {
err := breaker.Execute(failingOperation)
if err != nil {
fmt.Printf(" 调用 %d: ❌ %v\n", i, err)
}
}
// 3. 降级处理演示
fmt.Printf("\n 📉 降级处理测试:\n")
// 主要服务(模拟慢响应)
primaryService := func() (interface{}, error) {
time.Sleep(200 * time.Millisecond) // 模拟慢响应
return "来自主要服务的数据", nil
}
// 降级服务(快速响应)
fallbackService := func() (interface{}, error) {
return "来自缓存的数据", nil
}
handler := NewFallbackHandler(primaryService, fallbackService, 100*time.Millisecond)
result, err := handler.Execute()
if err != nil {
fmt.Printf(" ❌ 降级处理失败: %v\n", err)
} else {
fmt.Printf(" ✅ 降级处理成功: %v\n", result)
}
fmt.Printf("\n 📋 错误恢复最佳实践:\n")
fmt.Printf(" 1. 识别可重试的错误类型\n")
fmt.Printf(" 2. 实现指数退避重试策略\n")
fmt.Printf(" 3. 使用熔断器防止级联失败\n")
fmt.Printf(" 4. 提供降级和备用方案\n")
fmt.Printf(" 5. 设置合理的超时时间\n")
fmt.Printf(" 6. 监控错误率和恢复情况\n")
}
func main() {
demonstrateErrorHandlingStrategy()
}:::
🎯 核心知识点总结
错误分类体系要点
- 按性质分类: 业务错误、系统错误、网络错误等
- 按严重程度: 低、中、高、严重四个级别
- 按处理方式: 可重试、不可重试、临时性错误
- 标准化信息: 错误码、消息、上下文、堆栈信息
自定义错误要点
- 错误包装: 保留原始错误同时添加上下文信息
- 错误链: 构建多个错误的聚合和链式传播
- 业务包装: 区分用户友好消息和技术详情
- 元数据携带: 附加诊断和调试信息
错误传播要点
- 过滤机制: 根据严重程度决定是否传播错误
- 错误转换: 适配不同层级的错误类型
- 上下文增强: 添加服务、版本、时间戳等信息
- 链路追踪: 保持错误在调用链中的完整传播
错误恢复要点
- 重试策略: 指数退避、最大重试次数、可重试错误判断
- 熔断保护: 防止故障扩散和级联失败
- 降级处理: 提供备用方案和缓存数据
- 超时控制: 避免无限等待和资源占用
🔍 面试准备建议
- 理解原理: 深入理解Go错误处理的设计思想和最佳实践
- 设计能力: 掌握企业级错误处理体系的设计方法
- 实践经验: 积累不同场景下的错误处理实际经验
- 工具使用: 熟悉错误监控、追踪和分析工具
- 系统思维: 从系统可靠性角度思考错误处理策略
