政府网站建设策划书/建立免费网站

政府网站建设策划书,建立免费网站,泊头网站建设甘肃,找人做企业网站注意啥提示: 所有体系课见专栏:Go 项目开发极速入门实战课;欢迎加入 云原生 AI 实战 星球,12 高质量体系课、20 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);本节课最终…

提示:

  • 所有体系课见专栏:Go 项目开发极速入门实战课;
  • 欢迎加入 云原生 AI 实战 星球,12+ 高质量体系课、20+ 高质量实战项目助你在 AI 时代建立技术竞争力(聚焦于 Go、云原生、AI Infra);
  • 本节课最终源码位于 fastgo 项目的 feature/s10 分支;
  • 更详细的课程版本见:Go 项目开发中级实战课:16 | 基础 Go 包开发:错误返回设计和实现

在 Go 项目开发中,为了方便客户端处理返回,排查错误,还需要实现统一的错误返回。统一的错误返回包括以下 2 个方面:

  • 错误格式统一:返回统一的错误格式,方便客户端解析,并获取错误;
  • 自定义业务错误码:HTTP 的错误码有限,并且不适合业务错误码。所以,在实际开发中,还需要自定义业务错误码。

为了实现统一的错误返回,接下来还需要实现错误包和自定义错误码。

错误返回方法

先来看下错误返回的方式。在 Go 项目开发中,错误的返回方式通常有以下两种:

  1. 始终返回 HTTP 200 状态码,并在 HTTP 返回体中返回错误信息;
  2. 返回 HTTP 400 状态码(Bad Request),并在 HTTP 返回体中返回错误信息。

方式一:成功返回,返回体中返回错误信息

例如 Facebook API 的错误返回设计,始终返回 200 HTTP 状态码:

{"error": {"message": "Syntax error \"Field picture specified more than once. This is only possible before version 2.1\" at character 23: id,name,picture,picture","type": "OAuthException","code": 2500,"fbtrace_id": "xxxxxxxxxxx"}
}

在上述错误返回的实现方式中,HTTP 状态码始终固定返回 200,仅需关注业务错误码,整体实现较为简单。然而,此方式存在一个明显的缺点:对于每一次 HTTP 请求,既需要检查 HTTP 状态码以判断请求是否成功,还需要解析响应体以获取业务错误码,从而判断业务逻辑是否成功。理想情况下,我们期望客户端对成功的 HTTP 请求能够直接将响应体解析为需要的 Go 结构体,并进行后续的业务逻辑处理,而不用再判断请求是否成功。

方式二:失败返回,返回体中返回错误信息

Twitter API 的错误返回设计会根据错误类型返回对应的 HTTP 状态码,并在返回体中返回错误信息和自定义业务错误码。成功的业务请求则返回 200 HTTP 状态码。例如:

HTTP/1.1 400 Bad Request
x-connection-hash: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
set-cookie: guest_id=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Date: Thu, 01 Jun 2017 03:04:23 GMT
Content-Length: 62
x-response-time: 5
strict-transport-security: max-age=631138519
Connection: keep-alive
Content-Type: application/json; charset=utf-8
Server: tsa_b{"errors": [{"code": 215,"message": "Bad Authentication data."}]
}

方式二相比方式一,对于成功的请求不需要再次判错。然而,方式二还可以进一步优化:整数格式的业务错误码 215 可读性较差,用户无法从 215 直接获取任何有意义的信息。建议将其替换为语义化的字符串,例如:NotFound.PostNotFound

Twitter API 返回的错误是一个数组,在实际开发获取错误时,需要先判断数组是否为空,如不为空,再从数组中获取错误,开发复杂度较高。建议采用更简单的错误返回格式:

{"code": "InvalidParameter.BadAuthenticationData","message": "Bad Authentication data."
}

需要特别注意的是,message 字段会直接展示给外部用户,因此必须确保其内容不包含敏感信息,例如数据库的 id 字段、内部组件的 IP 地址、用户名等信息。返回的错误信息中,还可以根据需要返回更多字段,例如:错误指引文档 URL 等。

fastgo 错误返回设计和实现

fastgo 项目错误返回格式采用了方式二,在接口失败时返回对应的 HTTP/gRPC 状态码,并在返回体中返回具体的错误信息,例如:

HTTP/1.1 404 Not Found
...
{"code": "NotFound.UserNotFound","message": "User not found."
}

制定错误码规范

错误码是直接暴露给用户的,因此需要设计一个易读、易懂且规范化的错误码。在设计错误码时可以根据实际需求自行设计,也可以参考其他优秀的设计方案。

一般来说,当调研某项技术实现时,建议优先参考各大公有云厂商的实现方式,例如腾讯云、阿里云、华为云等。这些公有云厂商直接面向企业和个人,专注于技术本身,拥有强大的技术团队,因此它们的设计与实现具有很高的参考价值。

经过调研,此处采用了腾讯云 API 3.0 的错误码设计规范。腾讯云采用了两级错误码设计。以下是两级错误码设计相较于简单错误码(如 215、InvalidParameter)的优势:

  • 语义化: 语义化的错误码可以通过名字直接反映错误的类型,便于快速理解错误;
  • 更加灵活: 二级错误码的格式为<平台级.资源级>。其中,平台级错误码是固定值,用于指代某一类错误,客户端可以利用该错误码进行通用错误处理。资源级错误码则用于更精确的错误定位。此外,服务端既可根据需求自定义错误码,也可使用默认错误码。

fastgo 项目预定义了一些错误码,这些错误码位于以下 3 个文件中:

  • internal/pkg/errorsx/code.go:定义了一些通用的错误码;
  • internal/pkg/errorsx/user.go:定义了用户相关的错误码;
  • internal/pkg/errorsx/post.go:定义了博客相关的错误码。

一些错误码举例解释如下:

错误码错误描述错误类型
OK请求成功-
InternalError内部错误1
NotFound资源不存在0

上表中,错误类型 0 代表客户端错误,1 代表服务端错误,2 代表客户端错误/服务端错误,- 代表请求成功。

fastgo 错误包设计

为了避免与标准库的 errors 包命名冲突,fastgo 项目的错误包命名为 errorsx,寓意为“扩展的错误处理包”。

由于 fastgo 项目的错误包命名为 errorsx,为保持命名一致性,定义了一个名为 ErrorX 的结构体,用于描述错误信息,具体定义如下:

// ErrorX 定义了 OneX 项目体系中使用的错误类型,用于描述错误的详细信息.
type ErrorX struct {// Code 表示错误的 HTTP 状态码,用于与客户端进行交互时标识错误的类型.Code int `json:"code,omitempty"`// Reason 表示错误发生的原因,通常为业务错误码,用于精准定位问题.Reason string `json:"reason,omitempty"`// Message 表示简短的错误信息,通常可直接暴露给用户查看.Message string `json:"message,omitempty"`
}

ErrorX 是一个错误类型,因此需要实现 Error 方法:

// Error 实现 error 接口中的 `Error` 方法.
func (err *ErrorX) Error() string {return fmt.Sprintf("error: code = %d reason = %s message = %s", err.Code, err.Reason, err.Message)
}

Error() 返回的错误信息中,包含了 HTTP 状态码、错误发生的原因、错误信息。通过这些详尽的错误信息返回,帮助开发者快速定位错误。

在 Go 项目开发中,发生错误的原因有很多,大多数情况下,开发者希望将真实的错误信息返回给用户。因此,还需要提供一个方法用来设置 ErrorX 结构体中的 Message 字段。为了满足上述诉求,给 ErrorX 增加 WithMessage方法。实现方式如下是代码所示(位于文件 internal/pkg/errorsx/errorsx.go 中):

// ErrorX 定义了 fastgo 项目中使用的错误类型,用于描述错误的详细信息.
type ErrorX struct {// Code 表示错误的 HTTP 状态码,用于与客户端进行交互时标识错误的类型.Code int `json:"code,omitempty"`// Reason 表示错误发生的原因,通常为业务错误码,用于精准定位问题.Reason string `json:"reason,omitempty"`// Message 表示简短的错误信息,通常可直接暴露给用户查看.Message string `json:"message,omitempty"`
}// New 创建一个新的错误.
func New(code int, reason string, format string, args ...any) *ErrorX {return &ErrorX{Code:    code,Reason:  reason,Message: fmt.Sprintf(format, args...),}
}// Error 实现 error 接口中的 `Error` 方法.
func (err *ErrorX) Error() string {return fmt.Sprintf("error: code = %d reason = %s message = %s", err.Code, err.Reason, err.Message)
}// WithMessage 设置错误的 Message 字段.
func (err *ErrorX) WithMessage(format string, args ...any) *ErrorX {err.Message = fmt.Sprintf(format, args...)return err
}

在 Go 项目开发中,通常需要将一个 error 类型的错误 err,解析为 *ErrorX 类型,并获取 *ErrorX 中的 Code 字段和 Reason 字段的值。Code 字段可用来设置 HTTP 状态码,Reason 字段可用来判断错误类型。为此,errorsx 包实现了 FromError 方法,具体实现如下所示。

// FromError 尝试将一个通用的 error 转换为自定义的 *ErrorX 类型.
func FromError(err error) *ErrorX {// 如果传入的错误是 nil,则直接返回 nil,表示没有错误需要处理.if err == nil {return nil}// 检查传入的 error 是否已经是 ErrorX 类型的实例.// 如果错误可以通过 errors.As 转换为 *ErrorX 类型,则直接返回该实例.if errx := new(ErrorX); errors.As(err, &errx) {return errx}// 默认返回未知错误错误. 该错误代表服务端出错return New(ErrInternal.Code, ErrInternal.Reason, err.Error())
}

fastgo 错误码定义

在实现了 errorsx 错误包之后,便可以根据需要预定义项目需要的错误。这些错误,可以在代码中便捷的引用。通过直接引用预定义错误,不仅可以提高开发效率,还可以保持整个项目的错误返回是一致的。

fastgo 的预定义错误定义在 internal/pkg/errorsx 目录下。一些基础错误定义如下:

// errorsx 预定义标准的错误.
var (// OK 代表请求成功.OK = &ErrorX{Code: http.StatusOK, Message: ""}// ErrInternal 表示所有未知的服务器端错误.ErrInternal = &ErrorX{Code: http.StatusInternalServerError, Reason: "InternalError", Message: "Internal server error."}// ErrNotFound 表示资源未找到.ErrNotFound = &ErrorX{Code: http.StatusNotFound, Reason: "NotFound", Message: "Resource not found."}
)

更完整的预定义错误,可直接查看 master 分支中,internal/pkg/errorsx 中的错误定义文件。

fastgo 错误返回规范

为了标准化接口错误返回,fastgo 项目提供了通用的接口返回函数,该函数可以解析错误,并返回固定的错误返回格式。实现代码位于 internal/pkg/core/core.go 文件中,代码内容如下:

package coreimport ("net/http""github.com/gin-gonic/gin""github.com/onexstack/fastgo/internal/pkg/errorsx"
)// ErrorResponse 定义了错误响应的结构,
// 用于 API 请求中发生错误时返回统一的格式化错误信息.
type ErrorResponse struct {// 错误原因,标识错误类型Reason string `json:"reason,omitempty"`// 错误详情的描述信息Message string `json:"message,omitempty"`
}// WriteResponse 是通用的响应函数.
// 它会根据是否发生错误,生成成功响应或标准化的错误响应.
func WriteResponse(c *gin.Context, err error, data any) {if err != nil {// 如果发生错误,生成错误响应errx := errorsx.FromError(err) // 提取错误详细信息c.JSON(errx.Code, ErrorResponse{Reason:  errx.Reason,Message: errx.Message,})return}// 如果没有错误,返回成功响应c.JSON(http.StatusOK, data)
}

上述代码,定义了一个通用的错误返回结构体:ErrorResponse。ErrorResponse 中包含了错误返回的原因和消息。

在 API 接口返回时,会调用 WriteResponse 函数。WriteResponse 函数会判断是否发生了错误,如果发生了错误,会解析错误为 errorsx.ErrorX 类型的错误,并从中获取 CodeReason 字段,并设置给ErrorResponse 类型的变量。如果没有发生错误,直接返回自定义数据。

返回统一的错误格式

上面,我们开发了错误包、自定义了错误返回码,并提供了接口返回函数 WriteResponse。接下来,就可以使用 WriteResponse 来返回接口数据。

更新 internal/apiserver/server.go 文件中的 NoRoute 返回实现和 /healthz 接口的返回实现。代码变更如下:

package apiserverimport (..."github.com/onexstack/fastgo/internal/pkg/core""github.com/onexstack/fastgo/internal/pkg/errorsx"...
)
...
// NewServer 根据配置创建服务器.
func (cfg *Config) NewServer() (*Server, error) {...// 注册 404 Handler.engine.NoRoute(func(c *gin.Context) {core.WriteResponse(c, errorsx.ErrNotFound.WithMessage("Page not found"), nil)})// 注册 /healthz handler.engine.GET("/healthz", func(c *gin.Context) {core.WriteResponse(c, nil, map[string]string{"status": "ok"})})...
}

上述代码通过调用 WriteResponse 返回了标准的错误返回。并且在 NoRoute 路由函数中,还指定了要返回的自定义错误码 ErrNotFound,并给 ErrNotFound 设置了自定义返回消息。

编译并测试

运行以下命令编译并测试错误返回功能:

$ ./build.sh 
$ _output/fg-apiserver -c configs/fg-apiserver.yaml

打开一个新的 Linux 终端,执行以下命令:

$ curl http://127.0.0.1:6666/noroute
{"reason":"NotFound","message":"Page not found"}

可以看到,当我们方位一个不存在的路径时,返回了自定义错误码及自定义消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/897623.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

DeepSeek结合Mermaid绘图(流程图、时序图、类图、状态图、甘特图、饼图)转载

思维速览&#xff1a; 本文将详细介绍如何利用DeepSeek结合Mermaid语法绘制各类专业图表&#xff0c;帮助你提高工作效率和文档质量。 ▍DeepSeek入门使用请看&#xff1a;deepseek保姆级入门教程&#xff08;网页端使用 本地客户端部署 使用技巧&#xff09; DeepSeek官网…

上下分层、左右分离的驱动设计思想

之前了解了最简单的驱动程序、但是不易扩展、现在继续学习、上下分层、左右分离的驱动设计思想。 1、led_dev.c函数 上层函数&#xff0c;①定义一个结构体&#xff0c;存储函数用来接应app的函数。②定义一个入口函数&#xff0c;将我们接应的函数告诉内核&#xff0c;给这个…

《历史代码分析》5、动态控制列表的列

​​ 本系列《历史代码分析》为工作中遇到具有代表性的代码。今天我们讲一下&#xff0c;动态展示列表的列&#xff0c;因为找不到代码了&#xff0c;所有本篇用图展示。 举个栗子 ​​ 我们希望能够动态的控制列表的列&#xff0c;例如&#xff0c;英语老师只想知道自己学…

Windows HD Video Converter Factory PRO-v27.9.0-

Windows HD Video Converter Factory PRO 链接&#xff1a;https://pan.xunlei.com/s/VOL9TaiuS7rXbu-1kEDndoceA1?pwd7qch# 支持300多种视频格式转换&#xff0c;在保留视频质量的同时&#xff0c;压缩率可达80%&#xff0c;转换速度可达50X速率&#xff01; 支持画面剪切、片…

##Hive安装-初始化元数据报错 *** schemaTool failed ***

报错&#xff1a; org.apache.hadoop.hive.metastore.HiveMetaException: Failed to get schema version. Underlying cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException : Communications link failure 解决方案&#xff1a; 尝试一&#xff1a;javax.jdo.o…

远程手机遥控开关原理及应用

远程手机遥控开关的工作原理主要是通过互联网传递无线信号&#xff0c;控制用电器的一种智能家居产品。 远程手机遥控开关的基本套件包括&#xff1a;手机APP、网线、家用WIFI中转无服务器或者是工厂提供的自带网线端口的中转服务器、连接用电器的接收器。使用时&#xff0c;手…

Mac java全栈开发环境配置

前言 由于最近手中的windows本子坏了,所以搞了一台m系列的macbookpro 作为一个开发者 面对新设备最先考虑的应该就是各种sdk、中间件服务、环境变量配置和工具了吧!!! 本文将带你手把手学习Mac搭建属于自己的本地开发环境 安装brew 什么是brew? ‌Brew(全称Homebrew)…

HTMLCSS绘制三角形

1.代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>01triangle</title><s…

vue3-element-admin 前后端本地启动联调

一、后端环境准备 1.1、下载地址 gitee 下载地址 1.2、环境要求 JDK 17 1.3、项目启动 克隆项目 git clone https://gitee.com/youlaiorg/youlai-boot.git数据库初始化 执行 youlai_boot.sql 脚本完成数据库创建、表结构和基础数据的初始化。 修改配置 application-dev.y…

WinForm模态与非模态窗体

1、模态窗体 1&#xff09;定义&#xff1a; 模态窗体是指当窗体显示时&#xff0c;用户必须先关闭该窗体&#xff0c;才能继续与应用程序的其他部分进行交互。 2&#xff09;特点&#xff1a; 窗体以模态方式显示时&#xff0c;会阻塞主窗体的操作。用户必须处理完模态窗体上…

Agisoft Metashape 创建分块建模

Agisoft Metashape 创建分块建模 文章目录 Agisoft Metashape 创建分块建模前言一、构建分块模型1.1、设置模型范围1.2、参数设置二、构建纹理三、导出分块模型3.1整体导出3.2单独导出选定的分块四、编辑分块模型前言 从 Agisoft Metashape Professional 的 2.1. 版本开始,就…

MinIO的预签名直传机制

我们传统使用MinIo做OSS对象存储的应用方式往往都是在后端配置与MinIO的连接和文件上传下载的相关接口&#xff0c;然后我们在前端调用这些接口完成文件的上传下载机制&#xff0c;但是&#xff0c;当并发量过大&#xff0c;频繁访问会对后端的并发往往会对服务器造成极大的压力…

手把手教你用Docker搭建gitlab

文章目录 前言一、安装Docker二、安装GItlab三、配置Gitlab四、备份五、Docker数据持久化总结 前言 如题所述&#xff0c;手把手带你搭建gitlab&#xff0c;目标是实现ssh链接clone项目&#xff0c;不会我随你怎么说。 说正题&#xff0c;GitLab 是一个基于 Git 的全面 DevOps…

基于springboot住院管理系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 随着世界经济信息化、全球化的到来和电子商务的飞速发展&#xff0c;推动了很多行业的改革。若想达到安全&#xff0c;快捷的目的&#xff0c;就需要拥有信息化的组织和管理模式&#xff0c;建立一套合理、畅通、高效的线上管理系统。当前的住院管理存在管理效率低下&…

数据采集技术之python网络爬虫(中国天气网的爬取)

一、爬取中国天气网所有地区当天的天气数据&#xff08;PyCharm&#xff09;&#xff1a; 网址&#xff1a;https://www.weather.com.cn/ 下面爬取数据&#xff1a; 因为现在已经到了夜间&#xff0c;所以白天的数据已经不见了&#xff0c;但原理是一样的。 二、代码以及详情…

Ollama本地部署deepseek-r1蒸馏版

Docker安装Ollama 拉取镜像 docker pull ollama/ollama​ 启动-使用GPU docker run -d --gpusall -p 11434:11434 --name ollama ollama/ollamadocker run : Docker 的核心命令&#xff0c;用于创建并启动一个新的容器。 -d : 后台模式&#xff08;detached mode&#xff09…

41.HarmonyOS NEXT Layout布局组件系统详解(八):自定义样式与类

温馨提示&#xff1a;本篇博客的详细代码已发布到 git : https://gitcode.com/nutpi/HarmonyosNext 可以下载运行哦&#xff01; HarmonyOS NEXT Layout 布局组件系统详解&#xff08;八&#xff09;&#xff1a;自定义样式与类 文章目录 HarmonyOS NEXT Layout 布局组件系统详…

【Go | 从0实现简单分布式缓存】-7:增加etcd和gRPC功能

本文目录 1.序2.引入etcd缓存流程项目结构 3.gocachepb.proto4.服务注册register.go5.服务发现discover.go6.gRPC客户端client.gopeers.goclient.go 7.gRPC服务端实现server.go一些问题缓存获取流程缓存设置流程为什么要带超时的上下文&#xff1f; 1.序 GeeCache项目并没有引…

Pytorch系列教程:可视化Pytorch模型训练过程

深度学习和理解训练过程中的学习和进步机制对于优化性能、诊断欠拟合或过拟合等问题至关重要。将训练过程可视化的过程为学习的动态提供了有价值的见解&#xff0c;使我们能够做出合理的决策。训练进度必须可视化的两种方法是&#xff1a;使用Matplotlib和Tensor Board。在本文…

18 | 实现简洁架构的 Handler 层

提示&#xff1a; 所有体系课见专栏&#xff1a;Go 项目开发极速入门实战课&#xff1b;欢迎加入我的训练营&#xff1a;云原生AI实战营&#xff0c;一个助力 Go 开发者在 AI 时代建立技术竞争力的实战营&#xff1b;本节课最终源码位于 fastgo 项目的 feature/s14 分支&#x…