当前位置: 首页 > news >正文

开发网站公司名称沈阳网站关键字优化

开发网站公司名称,沈阳网站关键字优化,电商运营培训机构排名,专业信息门户网站定制大家好,我是peachesTao,今天给大家推荐一个go的支持多语言的error自动生成的插件,插件主页可以访问下方链接。 在一个多语言国际化的项目中,后端接口返回给前端的错误描述也需要国际化,我们来看一下后端给前端返回多语…

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

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

常规实现

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

1、定义Error结构体

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

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

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

const (Err_Code_Success       = 0Err_Code_UnKnown       = -1Err_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 boolif e, ok = err.(*Error); !ok {e = &Error{Code: Err_Code_UnKnown}}}msg := errMap[language][e.Code]res := make(map[string]interface{})res["code"] = e.Coderes["msg"] = msgjson, _ := 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.SUCCESSvar ok boolif 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.Coderes["msg"] = e.Msgjson, _ := 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

http://www.hrbkazy.com/news/10338.html

相关文章:

  • 宿豫网站建设制作免费发帖推广网站
  • 济南网站建设报价黑帽seo技术
  • 徐东做网站网站排名提升软件
  • 网站制作工具新品推广计划与方案
  • 互联网网站制作公司网络优化工程师为什么都说坑人
  • 建行个人网上银行seo对网站优化
  • 凡科做的网站好吗seo工具不包括
  • 比较知名的设计网站有哪些网络seo软件
  • 教育中介公司网站建设费用深圳专业seo外包
  • 做谷歌外贸较好网站seo成功的案例和分析
  • 做海岛旅游类网站的背景及意义志鸿优化设计官网
  • 深圳建设局招标网站谷歌关键词排名查询工具
  • 网站建设主要问题网站友情链接代码
  • 有效推广网站360开户
  • 国外哪个网站卖真松树做圣诞树域名停靠网页推广大全
  • dw做单页网站教程网站建设的好公司
  • 投诉网站建设seo推广平台服务
  • 银川网站建设哪家不错网络游戏推广公司
  • 物流系统网站建设 的网站描述正规营销培训
  • 长沙快速网页制作福州seo按天收费
  • wordpress删除多余图片上海网络公司seo
  • 南京做网站建设google play下载安装
  • 乌鲁木齐网站制作公司可靠吗网络营销的特点有
  • 怎么做网站底部备案号东莞全网推广
  • 网站建设柒首先金手指6为什么打开网址都是站长工具
  • 安阳 网站建设长沙推广引流
  • wordpress适用于图片站的主题网站服务器速度对seo有什么影响
  • 引擎搜索网站模板百度广告开户流程
  • 适合新手做的网站网站推广的具体方案
  • 假如做网站推广如何推广守游网络推广平台登陆