一个go的支持多语言的error自动生成插件

这篇具有很好参考价值的文章主要介绍了一个go的支持多语言的error自动生成插件。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

大家好,我是peachesTao,今天给大家推荐一个go的支持多语言的error自动生成的插件,插件主页可以访问下方链接。

在一个多语言国际化的项目中,后端接口返回给前端的错误描述也需要国际化,我们来看一下后端给前端返回多语言错误描述的实现方式有哪些。

常规实现

服务端将错误码和不同语言的错误描述硬编码在代码中,通过前端从http head中传过来的language来决定是返回中文还是英文。

1、定义Error结构体

该结构体实现标准库的error接口,实现自定义error

type Error struct {
	Code int
	Msg  string
}

func (e *Error) Error() string {
	return fmt.Sprintf("%d,%s", e.Code, e.Msg)
}

2、定义错误码和错误描述map

const (
	Err_Code_Success       = 0
	Err_Code_UnKnown       = -1
	Err_Code_InValid_Phone = 10001
)

const (
	Language_Chinese = 0 //中文
	Language_Enligh  = 1 //英文
)

//不同语言对应的错误描述
var errMap = map[int]map[int]string{
	Language_Chinese: {
		Err_Code_Success:       "成功",
		Err_Code_InValid_Phone: "手机号格式不正确",
		Err_Code_UnKnown:       "未知错误",
	},
	Language_Enligh: {
		Err_Code_Success:       "success",
		Err_Code_InValid_Phone: "invalid phone no",
		Err_Code_UnKnown:       "unknown err",
	},
}

3、申明一个用户注册的api

根据客户端传过来的http header中的language的值决定返回中文还是英文的错误描述

func main() {
	http.HandleFunc("/user/register", func(w http.ResponseWriter, r *http.Request) {
		languageStr := r.Header.Get("language")
		language, _ := strconv.Atoi(languageStr)
		values, _ := url.ParseQuery(r.URL.RawQuery)
		phone := values["phone"][0]
		err := checkPhone(phone)
		response(w, language, err)
	})
	http.ListenAndServe(":8080", nil)
}

func response(w http.ResponseWriter, language int, err error) {
	e := &Error{Code: Err_Code_Success}
	if err != nil {
		var ok bool
		if e, ok = err.(*Error); !ok {
			e = &Error{Code: Err_Code_UnKnown}
		}
	}
	msg := errMap[language][e.Code]
	res := make(map[string]interface{})
	res["code"] = e.Code
	res["msg"] = msg
	json, _ := json.Marshal(res)
	w.WriteHeader(200)
	w.Write(json)
}

func checkPhone(phoneNo string) error {
	if len(phoneNo) != 11 {
		return &Error{Code: Err_Code_InValid_Phone}
	}
	return nil
}

我们通过curl命令来看看效果

语言设置为中文时:

curl -H "language:0" "http://127.0.0.1:8080/user/register?phone=187111111112"
{"code":10001,"msg":"手机号格式不正确"}

语言设置为英文时:

curl -H "language:1" "http://127.0.0.1:8080/user/register?phone=187111111112"
{"code":10001,"msg":"invalid phone no"}

这种实现方式确实能满足业务需求,但是有下面几个缺点:

  • 当要将手机号格式不正确的描述改时需要修改代码
  • 当添加新的错误时需要改动多个地方代码:添加新的错误码和在errMap中添加对应语言的错误描述,容易遗漏
  • 当添加新的语言时要向errMap添加所有错误码的新语言错误描述,容易遗漏

一旦涉及到修改代码就存在出现bug的风险。

有人会想到将错误描述放在json文件中维护,这种方案只是在修改错误描述时比较便利,不需要改动业务代码,但在新增错误和新语言时存在同样的问题。

还有一种方案是通过翻译包将文本翻译为目标语言,但这种方法翻译的结果不可控,且性能比较低。

有没有一种更优雅的方案,尽量减少修改代码,且有足够的灵活性?

下面我们来看看通过go-error-generator插件的方法来实现

更优雅的实现

go-error-generator是一个通过protobuf文件的Enum对象自动生成Error的插件,通过在扩展的EnumValueOptions中定义多个option轻松实现error的多语言。

它包含如下功能:

  • 根据Enum定义的errCode和msg自动生成error;
  • 支持定义多个EnumValueOption,实现多语言;
  • 支持error合并功能;
  • 支持自定义Error结构体、error Code和Msg的名称;

关于插件的原理和其他细节可以访问github主页了解。

我们回到刚才那个需求,用插件的方式怎么实现错误多语言

1、定义error模板

删除代码中的的Error结构体,取代的是在protobuf中定义,新建一个protobuf文件,取名为error.proto,在这里自定义error结构体和语言标识。

其中:

  • msg:默认的语言标识,在错误码定义文件中没有定义其他语言的错误描述时就用它的错误描述
  • msg_english:英文标识,当然你也可以取别的名字
syntax = "proto3";
package errors;
option go_package = "github.com/classtorch/go-error-generator-examples/internal/errors";
import "google/protobuf/descriptor.proto";

message Error {
  int32 code = 1;
  string msg = 2;
};
extend google.protobuf.EnumValueOptions {
  string msg = 1108;
  string msg_english = 1109;
}

2、定义错误码和错误描述

新建一个protobuf文件,取名为account.proto
导入上面定义好的error.proto,自定义msg和msg_english对应的错误描述

syntax = "proto3";
package uclass.service.account;
option go_package = "/golang/account";
import "errors/errors.proto";

enum ErrorCode {
  SUCCESS = 0 [(errors.msg) = "成功", (errors.msg_english) = "success"];  // 成功
  UnKnown = -1 [(errors.msg) = "未知错误", (errors.msg_english) = "unknown err"]; // 账号不存在
  InValid_Phone = 10001 [(errors.msg) = "手机号格式不正确", (errors.msg_english) = "invalid phone no"];  // 登录失效,请重新登录
}

3、通过插件生成代码

该插件需要安装go和protobuf运行环境

  • go
  • protoc
  • protoc-gen-go

安装好运行环境后再安装go-error-generator插件

go install github.com/classtorch/go-error-generator/protoc-gen-go-error-generator

安装好后执行下面脚本生成代码

protoc --go-error-generator_out=:. \
 --go-error-generator_opt descriptor_file=errors/errors.proto \
 --go-error-generator_opt merge_error=false \
 --go-error-generator_opt merge_error_path=golang/errors \
 --go_out=. -I . account.proto

插件自动生成的代码如下,包含error对象和error map

var (
	SUCCESS       = &errors.Error{Code: 0, Msg: "成功"}           //成功
	UnKnown       = &errors.Error{Code: -1, Msg: "未知错误"}        //未知错误
	InValid_Phone = &errors.Error{Code: 10001, Msg: "手机号格式不正确"} //手机号格式不正确
)

var (
	Msg = map[int32]*errors.Error{
		0:     &errors.Error{Code: 0, Msg: "成功"},
		-1:    &errors.Error{Code: -1, Msg: "未知错误"},
		10001: &errors.Error{Code: 10001, Msg: "手机号格式不正确"},
	}
  
	Msg_English = map[int32]*errors.Error{
		0:     &errors.Error{Code: 0, Msg: "success"},
		-1:    &errors.Error{Code: -1, Msg: "unknown err"},
		10001: &errors.Error{Code: 10001, Msg: "invalid phone no"},
	}
)

4、使用生成的error对象

使用生成的error对象和error map改写response和checkPhone方法

func response(w http.ResponseWriter, language int, err error) {
	e := account.SUCCESS
	var ok bool
	if err != nil {
		if e, ok = err.(*errors.Error); !ok {
			e = account.UnKnown
		}
	}
	if language == Language_Chinese {
		if e, ok = account.Msg[e.Code]; !ok {
			e = account.UnKnown
		}
	} else if language == Language_Enligh {
		if e, ok = account.Msg_English[e.Code]; !ok {
			e = account.UnKnown
		}
	}
	res := make(map[string]interface{})
	res["code"] = e.Code
	res["msg"] = e.Msg
	json, _ := json.Marshal(res)
	w.WriteHeader(200)
	w.Write(json)
}

func checkPhone(phoneNo string) error {
	if len(phoneNo) != 11 {
		return account.InValid_Phone
	}
	return nil
}

完整的代码可以访问go-error-generator-examples项目进行了解

我们来看下这是实现方式的优点

  • 当我们需要修改某个错误描述时直接在account.proto文件中修改,无须修改代码
  • 当需要增加新的错误时直接在account.proto文件中定义,生成代码后直接在业务代码中引用即可
  • 当添加新的语言时只需要在error.proto中增加新的语言标识即,然后在account.proto中引入即可

可以看出对于第一个和和第三个需求来说只需要修改protobuf文件,重新生成代码就可以,无须修改业务代码。第二个需求也只是简单的引入新的错误对象。

由于该插件是基于protobuf实现的,如果项目中没有使用prorobuf技术栈的话会带来一些引入成本。不过这点成本相对于频繁修改业务代码还是值得的。

相关链接

go-error-generator

go-error-generator-examples文章来源地址https://www.toymoban.com/news/detail-618977.html

到了这里,关于一个go的支持多语言的error自动生成插件的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 自动生成数据库设计文档,支持多数据源批量生成(Word文档)

          在做项目时通常使用PowerDesigner设计数据库,但在项目完成交付项目给客户的时候常常需要一份Word版本的数据库文档给客户,你不能指望每个客户都会用PowerDesigner,所以基于当前开发数据库生成数据库文档就是最佳选择,如果手动编写数据库文档那将是一件非常痛苦的

    2024年04月23日
    浏览(50)
  • 一个开源的全自动视频生成软件MoneyPrinterTurbo

    只需提供一个视频 主题 或 ,就可以全自动生成视频文案、视频素材、视频字幕、视频背景音乐,然后合成一个高清的短视频。 一:功能特性 完整的 MVC架构,代码 结构清晰,易于维护,支持 API 和 Web界面 支持视频文案 AI自动生成,也可以自定义文案 支持多种 高清

    2024年04月17日
    浏览(51)
  • AIGC:自动化内容生成,AI 的下一个引爆点?

    来源|晨山资本 作者|吴文超 晨山资本副总裁,主要关注底层技术创新、人工智能和信息安全等领域。曾主导并参与了优锘科技、达观数据、雪浪数制、摩尔元数、LinkedMe、富数科技等多个企业的投资。在加入晨山资本之前,吴文超曾就职于明略科技集团,从事大数据研发工

    2024年02月09日
    浏览(46)
  • 又发现一个好玩的 Pycharm 插件,通过AI自动生成代码块注释

    经常在开发代码块的过程中都需要写大量的注释来完成对代码块的说明。作为一名程序猿可能经常在抱怨别人开发的代码块没有注释或是注释不清楚,但我们自己又不想把大量的时间花费在代码块注释的编写上面。 今天要说的这款插件是Mintlify Doc Writer,不仅支持Python,同时

    2024年02月11日
    浏览(45)
  • DataEase开源BI工具安装_数据全量_增量同步_大屏拖拽自动生成_多数据源支持_数据血缘分析---大数据工作笔记0183

    我这里用的是Centos7.9安装的 可以通过uname -p来查看一下我们的电脑架构,可以看到是x86_64架构的  我们下第一个,这个是x86架构的,第二个arm架构的    然后解压到/opt/module中   然后再去重命名一下文件夹.  推荐200G  本地模式的功能比较多 推荐100G  

    2024年02月15日
    浏览(45)
  • 前端项目部署自动检测更新后通知用户刷新页面(前端实现,技术框架vue、js、webpack)——方案一:编译项目时动态生成一个记录版本号的文件

    当我们重新部署前端项目的时候,如果用户一直停留在页面上并未刷新使用,会存在功能使用差异性的问题,因此,当前端部署项目后,需要提醒用户有去重新加载页面。 vue、js、webpack 编译项目时动态生成一个记录版本号的文件 轮询(20s、自己设定时间)这个文件,判断版

    2024年02月02日
    浏览(64)
  • 自动生成测试用例_接口测试用例自动生成工具

    写用例之前,我们应该熟悉API的详细信息。建议使用抓包工具Charles或AnyProxy进行抓包。 我们先来了解一下另一个项目har2case 他的工作原理就是将当前主流的抓包工具和浏览器都支持将抓取得到的数据包导出为标准通用的 HAR 格式(HTTP Archive),然后 HttpRunner 将 HAR 格式的数据

    2024年02月05日
    浏览(64)
  • 抖音自动生成视频、字幕、自动上传发布

    点击进入https://github.com/Richard0403/dy-auto https://github.com/Richard0403/dy-auto/assets/14147304/21400a42-9296-4956-9517-ced8d8bf4737 名称 功能 ffmpeg 处理视频的生成,语音添加,字幕的添加等 微软SpeechStudio 文字合成语音 whisper 语音生成字幕 jieba3k 用于文案的提取 playwright 用于自动化操作 环

    2024年02月08日
    浏览(57)
  • python自动生成SQL语句自动化

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。 在数据处理和管理中,SQL(Structured Query Language)是一种非常重要的语言。它用于在关系型数据库中执行各种操作,如查询、插入、更新和删

    2024年04月28日
    浏览(68)
  • 源生成器:根据需要自动生成机械重复代码

    本文概述了利用.NET Compiler Platform(“Roslyn”)SDK 附带的 源生成器 (Source Generator)自动生成机械重复的代码。关于这部分的基础入门知识可以在MSDN [1] 学到。 本文 默认 已经有一个解决方案,包含两个项目。一个是普通C#项目,依赖于另一个源生成器项目。 此处以 Dependenc

    2024年02月01日
    浏览(77)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包