Golang公共API返回错误的规范建议有哪些

来源:Java编程网作者:小雨头衔:草根站长
导读:本期聚焦于小伙伴创作的《Golang公共API返回错误的规范建议有哪些》,敬请观看详情,探索知识的价值。以下视频、文章将为您系统阐述其核心内容与价值。如果您觉得《Golang公共API返回错误的规范建议有哪些》有用,将其分享出去将是对创作者最好的鼓励。

在Golang开发公共API时,错误返回的设计是接口易用性的核心影响因素之一。不合理的错误返回会让调用方难以判断错误类型、定位问题根源,也会增加后续接口迭代的维护成本。本文将从多个维度给出Golang公共API返回错误的规范建议,帮助开发者设计出更友好的公共接口。

Golang公共API返回错误的规范建议有哪些

优先使用error接口作为错误返回载体

Golang内置的error接口是处理错误的标准方式,公共API应优先将错误作为函数的最后一个返回值,遵循值, error的返回顺序,不要自定义其他错误返回格式。调用方可以通过标准的方式判断错误是否存在,不需要额外学习接口的错误处理逻辑。

错误返回的基本规范示例如下:

package mathutil

import "errors"

// Add 两个整数相加的公共API
// 当输入参数出现溢出时返回错误
func Add(a, b int) (int, error) {
    // 模拟溢出判断
    if a > 0 && b > 0 && a > (1<<31-1)-b {
        return 0, errors.New("int add overflow")
    }
    return a + b, nil
}

避免使用基础类型错误,自定义错误类型传递更多信息

如果公共API需要让调用方区分不同的错误类型,或者需要传递错误码、上下文信息等额外内容,应该自定义实现error接口的结构体,而不是仅返回字符串类型的错误。自定义错误类型可以通过类型断言让调用方精准判断错误类别,也方便后续扩展错误信息字段。

自定义错误类型的实现示例:

package apierror

// APIError 公共API自定义错误类型
type APIError struct {
    Code    int    // 错误码
    Message string // 错误描述
    Cause   error  // 原始错误
}

// Error 实现error接口
func (e *APIError) Error() string {
    if e.Cause != nil {
        return e.Message + ": " + e.Cause.Error()
    }
    return e.Message
}

// 预定义常见错误实例
var (
    ErrInvalidParam = &APIError{Code: 1001, Message: "invalid parameter"}
    ErrNotFound     = &APIError{Code: 1002, Message: "resource not found"}
)

错误信息要简洁明确,包含必要的上下文

公共API返回的错误信息需要同时满足两个要求:一是简洁易懂,调用方不需要额外查文档就能知道错误的大致原因;二是包含必要的上下文,比如哪个参数不合法、哪个资源不存在,方便调用方快速定位问题。不要返回空的错误信息,也不要返回过于模糊的描述比如error occurred

错误信息编写的正确和错误示例对比:

场景错误示例正确示例
参数校验失败errors.New("param error")errors.New("param age must be greater than 0, got -5")
资源不存在errors.New("not found")errors.New("user with id 123 not found")

错误包装使用fmt.Errorf时保留原始错误链

当公共API内部调用其他函数返回错误时,如果需要添加上下文信息,应该使用fmt.Errorf结合%w动词包装错误,而不是用%v丢弃原始错误。保留错误链后,调用方可以通过errors.Iserrors.As方法判断原始错误类型,方便做针对性的错误处理。

错误包装的示例:

package userapi

import (
    "database/sql"
    "fmt"
    "github.com/yourname/apierror"
)

// GetUserByID 根据ID获取用户的公共API
func GetUserByID(id int) (*User, error) {
    user, err := queryUserFromDB(id)
    if err != nil {
        // 使用%w包装原始错误,保留错误链
        if err == sql.ErrNoRows {
            return nil, fmt.Errorf("get user failed: %w", apierror.ErrNotFound)
        }
        return nil, fmt.Errorf("get user failed, id: %d: %w", id, err)
    }
    return user, nil
}

不要忽略错误直接返回nil

公共API内部如果调用了返回错误的函数,一定要处理错误或者将错误向上传递,不要忽略错误直接返回nil。忽略错误会导致调用方无法感知内部的问题,出现不符合预期的行为,增加问题排查的难度。如果确实不需要处理错误,也应该在代码中添加注释说明忽略的原因。

错误处理的错误和正确示例:

// 错误示例:忽略错误直接返回
func SaveUser(user *User) error {
    _, err := db.Insert(user)
    // 忽略了插入的错误,直接返回nil
    return nil
}

// 正确示例:传递错误
func SaveUser(user *User) error {
    _, err := db.Insert(user)
    if err != nil {
        return fmt.Errorf("save user failed: %w", err)
    }
    return nil
}

预定义公共错误实例,避免重复的error创建

对于公共API中频繁出现的错误,比如参数不合法、资源不存在、权限不足等,应该预定义对应的错误实例,而不是每次返回错误时都新建errors.New。预定义错误实例可以让调用方通过errors.Is直接判断错误类型,也减少了重复代码的编写。

预定义错误的使用示例:

package userapi

import "github.com/yourname/apierror"

// 预定义当前包的公共错误
var (
    ErrInvalidUserID   = apierror.NewAPIError(2001, "invalid user id")
    ErrUserAlreadyExist = apierror.NewAPIError(2002, "user already exist")
)

func CreateUser(id int, name string) error {
    if id <= 0 {
        return ErrInvalidUserID
    }
    // 其他逻辑
    return nil
}

不要在错误中暴露敏感信息

公共API返回的错误信息中不要包含敏感内容,比如数据库连接字符串、内部服务地址、用户密码、密钥等信息。这些信息如果被外部获取,会带来安全风险。错误信息应该只包含调用方需要知道的公开内容,敏感的内部细节应该记录到内部日志中,而不是返回给调用方。

注意:如果公共API是对内使用的,可以根据内部规范调整错误信息的详细程度,但如果是对外开放的公共API,必须严格避免敏感信息泄露。

保持错误返回的一致性

同一个公共API包中的所有函数,应该遵循统一的错误返回规则,包括错误类型、错误码格式、错误信息的编写风格等。不要出现部分函数返回自定义错误类型,部分函数返回字符串错误的情况,也不要部分错误带错误码,部分错误不带错误码。一致的错误返回规则可以降低调用方的学习成本,也方便调用方统一做错误处理。

Golang公共API错误返回error接口API设计规范修改时间:2026-06-28 22:54:37

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。