Skip to content

WithErrorHandler

注入全局错误处理回调,在错误返回调用方前拦截。

签名

go
func WithErrorHandler(handler func(error) error) ClientOption

作用

设置 Client.errorHandler。每个方法在返回错误前调用 handleError,若设了 handler 则优先调它。

🎨 一图抵千言

errorHandler 注入后,错误在返回调用方前的分流路径。

下面这张时序图展示运行时调用序列视角:从构造期注入 errorHandler,到请求期 doRequest 出错后被 handleError 拦截、转交自定义 fn、最终返回调用方的完整链路。

回调契约对照

入参出参典型用法
原始 error原错误日志记录、监控上报
原始 errornil吞掉特定错误
原始 error新错误错误转换/包装

回调契约

go
func(err error) error
  • 入参:原始错误
  • 返回:处理后的错误(可返回 nil 吞掉,或返回新错误转换)

示例

日志记录

go
client := ipapi.NewClient(
	ipapi.WithErrorHandler(func(err error) error {
		log.Printf("ipapi error: %v", err)
		return err // 继续向上抛
	}),
)

监控上报

go
ipapi.WithErrorHandler(func(err error) error {
	sentry.CaptureException(err)
	if apiErr, ok := err.(*ipapi.APIError); ok {
		metrics.IncCounter(apiErr.Reason)
	}
	return err
})

吞掉特定错误

go
ipapi.WithErrorHandler(func(err error) error {
	if errors.Is(err, ipapi.ErrReservedIP) {
		return nil // 保留地址不当错误
	}
	return err
})

错误转换

go
ipapi.WithErrorHandler(func(err error) error {
	if errors.Is(err, ipapi.ErrRateLimited) {
		return ErrTooBusy // 转成业务错误
	}
	return err
})

内部

下面这张类图展示结构关系视角:WithErrorHandler 作为 ClientOption 如何把 handler 注入 Client.errorHandler,以及 ClienthandleError/内部方法之间的持有与调用关系。

go
func WithErrorHandler(handler func(error) error) ClientOption {
	return func(c *Client) {
		c.errorHandler = handler
	}
}

handleError

go
func (c *Client) handleError(err error) error {
	if c.errorHandler != nil {
		return c.errorHandler(err)  // 优先
	}
	// ... 否则按 Reason 映射哨兵
}

⚠️ handler 优先级

设了 handler 后,handleError 不再Reason → 哨兵 映射。若你仍想要哨兵匹配,需在 handler 内自行调用,或返回原 err。

🚫 不要吞掉所有错误

返回 nil完全消除该错误,调用方拿到的 err=nil 会误以为成功,但 info 仍为 nil,极易触发 nil 指针 panic。仅吞掉你明确无害的特定哨兵错误(如 ErrReservedIP),永远不要无脑 return nil

💡 在 handler 内保留哨兵映射

若既要拦截又想保留哨兵匹配能力,可在 handler 内手动映射:

go
ipapi.WithErrorHandler(func(err error) error {
    log.Printf("ipapi error: %v", err)
    // 保留原始错误,让调用方仍可用 errors.Is 判断
    return err
})

或对特定错误做转换后,转换后的错误也应支持 errors.Is 链,否则会破坏调用方的 switch 判断。

🎯 典型场景速查

  • 可观测性:日志 + Sentry + Metrics 上报,原样返回 err
  • 业务适配:把 ErrRateLimited 转成业务侧的 ErrTooBusy
  • 容错降级:吞掉 ErrReservedIP 等非致命错误
  • 统一封装:用 WrapError 加操作上下文

下一步

基于 MIT 许可证发布