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

提供网站空间服务器wordpress伪静态说明

提供网站空间服务器,wordpress伪静态说明,做soho一定要做网站吗,技术支持 海安网站建设在之前的两篇文章中#xff0c;我们已经介绍过错误的一些优雅处理 75.错误码设计、实现统一异常处理和封装统一返回结果 88.Go设计优雅的错误处理 本文想继续写一篇#xff0c;可以作为工具包直接使用。也是记录一种新的思路和编码技巧#xff0c;同时创建错误的时候会自动…在之前的两篇文章中我们已经介绍过错误的一些优雅处理 75.错误码设计、实现统一异常处理和封装统一返回结果 88.Go设计优雅的错误处理 本文想继续写一篇可以作为工具包直接使用。也是记录一种新的思路和编码技巧同时创建错误的时候会自动打印日志还能提供堆栈信息。 目标 避免所有错误前都需要手动打印日志,最好自动打印规范化的日志;完整的上下文信息,便于排查定位;方便response封装,返回标准三元组;高扩展性; 代码如下 代码地址https://gitee.com/lymgoforIT/golang-trick/blob/master/42-bizerror/bizerror/bizerror.go 注google.golang.org/appengine/log需要在谷歌的云计算平台才能使用所以下面的代码需要根据实际情况替换日志包。否则会报 not an App Engine context错误 package bizerrorimport (bytescontextfmtgoogle.golang.org/appengine/logpath/filepathruntimestrconvstrings )// BizError 自定义Error类型(实现了go内嵌error接口) // 特性: // 1. 包含服务返回三元组(Code Msg status), 便于封装response // 2. 自动日志打印(NewBizError时打印) // 3. 根据可选参数可控制是否打印堆栈信息 // 4. 其他option拓展见使用说明 type BizError struct {code string // 错误码msg string // 错误信息status string // 状态level BizErrLevel // 日志级别默认是Error级别detail string // 需要打印的补充信息fnName string // 函数名storeStack bool // 是否打印堆栈信息stack []byte // 堆栈信息stackRows int // 堆栈信息最大打印层次depth int // 函数调用深度channelCode string // 下游错误码channelMsg string // 下游错误信息asyncFn func(context.Context, *BizError) // 异步执行函数 }// BizErrLevel 错误等级, 会影响日志打印时的level type BizErrLevel int8// BizErrOption BizError属性设置函数 type BizErrOption func(*BizError)const (// InfoLevel Info级别, 使用logs.CtxInfo打印日志InfoLevel BizErrLevel iota// WarnLevel Warn级别, 使用logs.CtxWarn打印日志WarnLevel// ErrorLevel Error级别, 使用logs.CtxError打印日志ErrorLevel )func (e BizError) Error() string {errInfo : fmt.Sprintf([%s] code%s, msg%s, channelCode%s, channelMsg%s, detail%s,e.fnName, e.code, e.msg, e.channelCode, e.channelMsg, e.detail)if e.storeStack {errInfo errInfo \n string(e.stack)}return errInfo }func (e BizError) GetCode() string {return e.code }func (e BizError) GetStatus() string {return e.status }func (e BizError) GetMsg() string {return e.msg } func (e BizError) GetDetail() string {return e.detail }func (e BizError) GetChannelCode() string {return e.channelCode }func (e BizError) GetChannelMsg() string {return e.channelMsg }func NewBizError(ctx context.Context, code, status, msg string, opts ...BizErrOption) *BizError {bizErr : BizError{code: code,msg: msg,status: status,level: ErrorLevel,storeStack: true,depth: 2, // 为0时是getCurrentFunc,为1时是NewBizError为2时则是调用NewBizError的函数stackRows: 10,}for _, opt : range opts {opt(bizErr)}if len(bizErr.fnName) 0 {bizErr.fnName getCurrentFunc(bizErr.depth)}if bizErr.storeStack {bizErr.stack getStack(bizErr.depth, bizErr.stackRows)}bizErr.ctxLog(ctx)if bizErr.asyncFn ! nil {go safeGo(ctx, func() {bizErr.asyncFn(ctx, bizErr)})}return bizErr }func safeGo(ctx context.Context, f func()) {defer func() {if err : recover(); err ! nil {}}()f() }// WithLogLevelOption 设置日志打印等级, 不设置时默认为ErrorLevel func WithLogLevelOption(level BizErrLevel) BizErrOption {return func(e *BizError) {e.level level} }// WithDetailOption 设置报错详细信息, 如单号/Uid等参数 func WithDetailOption(format string, v ...interface{}) BizErrOption {return func(e *BizError) {e.detail fmt.Sprintf(format, v...)} }// WithFuncNameOption 设置打印日志时的报错函数名, 不设置时默认打印调用NewBizError的函数名 func WithFuncNameOption(funcName string) BizErrOption {return func(e *BizError) {e.fnName funcName} }// WithStackOption 设置是否保存函数栈信息, 不设置时默认保存 func WithStackOption(storeStack bool) BizErrOption {return func(e *BizError) {e.storeStack storeStack} }// WithSkipDepthOption 设置跳过的函数栈深度, 当你封装NewBizError时应该设置 func WithSkipDepthOption(skipDepth int) BizErrOption {return func(e *BizError) {e.depth skipDepth} }// WithChannelRespOption 设置下游返回的错误码/消息, 当异常是下游导致的可以设置 func WithChannelRespOption(channelCode, channelMsg string) BizErrOption {return func(e *BizError) {e.channelCode channelCodee.channelMsg channelMsg} }// WithAsyncExecutor 产生错误后异步执行器, 如进行上报metrics打点 func WithAsyncExecutor(fn func(context.Context, *BizError)) BizErrOption {return func(e *BizError) {e.asyncFn fn} }// WithStackRows 函数堆栈保存的行数, 默认保存10行 func WithStackRows(stackRows int) BizErrOption {return func(e *BizError) {if stackRows 0 {e.stackRows stackRows}} }// logFunc 定义日志打印函数,根据getLogFunc返回的实际指定的日志等级决定使用哪个函数 type logFunc func(ctx context.Context, format string, v ...interface{})// ctxLog 实际打印日志 func (e BizError) ctxLog(ctx context.Context) {e.getLogFunc()(ctx, %s, e.Error()) }// getLogFunc 根据日志等级获取日志打印函数默认为Error级别 func (e BizError) getLogFunc() logFunc {switch e.level {case InfoLevel:return log.Infofcase WarnLevel:return log.Warningfcase ErrorLevel:return log.Errorf}return log.Errorf }// getCurrentFunc 返回文件路径函数所在行数以及函数名 func getCurrentFunc(skip int) string {pc, file, line, ok : runtime.Caller(skip)if !ok {return ??:0:??()}funcName : runtime.FuncForPC(pc).Name()// 如 函数为/XXX/util.CallerTest则扩展名为.CallerTest,去掉左侧的.后为CallerTestfuncName strings.TrimLeft(filepath.Ext(funcName), .) ()return filepath.Base(file) : strconv.Itoa(line) : funcName }// getStack 返回一个格式良好的堆栈帧跳过跳过帧 func getStack(skip, rows int) []byte {buf : new(bytes.Buffer) // 返回数据// 在循环时打开文件并读取它们使用变量记录当前加载的文件for i : skip; i-skip rows; i { // 跳过最里层的skip帧pc, file, line, ok : runtime.Caller(i)if !ok {break}// 拼接当前所在栈的信息并换回继续去循环下一栈信息直到堆栈信息都打完或者达到rows层fmt.Fprintf(buf, %s:%d (0x%x)\n, file, line, pc)}return buf.Bytes() } 单元测试 package bizerrorimport (contextgithub.com/smartystreets/goconvey/conveygoogle.golang.org/appengine/logtestingtime )func TestBizError(t *testing.T) {ctx : context.Background()convey.Convey(NewBizError-无额外选项, t, func() {bizErr : NewBizError(ctx, code, status, msg)convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)})convey.Convey(NewBizError-增加详情, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithDetailOption(query failed with order id: %d, 123))convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)convey.So(bizErr.GetDetail(), convey.ShouldEqual, query failed with order id: 123)})convey.Convey(NewBizError-设置日志打印级别, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithLogLevelOption(InfoLevel))convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)bizErr2 : NewBizError(ctx, code, status, msg, WithLogLevelOption(WarnLevel))convey.So(bizErr2, convey.ShouldNotBeNil)})convey.Convey(NewBizError-设置函数名称, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithFuncNameOption(TestBizError))convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)})convey.Convey(NewBizError-设置不存储堆栈信息, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithStackOption(false))convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)})convey.Convey(NewBizError-设置堆栈行数, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithStackRows(2))convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)})convey.Convey(NewBizError-设置忽略的函数栈深度, t, func() {newCodeErr : func() *BizError {return NewBizError(ctx, code01, status01, msg01, WithSkipDepthOption(1))}bizErr : newCodeErr()convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code01)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status01)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg01)})convey.Convey(NewBizError-设置下游错误码/信息, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithChannelRespOption(channelCode, channelMsg))convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)convey.So(bizErr.GetChannelCode(), convey.ShouldEqual, channelCode)convey.So(bizErr.GetChannelMsg(), convey.ShouldEqual, channelMsg)})convey.Convey(NewBizError-设置异步执行器, t, func() {bizErr : NewBizError(ctx, code, status, msg, WithAsyncExecutor(func(ctx context.Context, bizError *BizError) {log.Infof(ctx, AsyncExecutor executed: bizError%s, bizError.Error())}))time.Sleep(1 * time.Second)convey.So(bizErr, convey.ShouldNotBeNil)convey.So(bizErr.GetCode(), convey.ShouldEqual, code)convey.So(bizErr.GetStatus(), convey.ShouldEqual, status)convey.So(bizErr.GetMsg(), convey.ShouldEqual, msg)}) }
http://www.zqtcl.cn/news/294584/

相关文章:

  • 做的不错的h5高端网站网站是怎么优化的
  • 淄博做网站优化佛山 做网站公司
  • 设计网站的步骤网站开发怎么学习
  • 提供网站技术国内外电子政务网站建设差距
  • 阜新建设网站物流网站建设的小结
  • 个人可以网站备案吗建设多用户网站
  • 平面设计素材库淄博网站优化价格
  • moodle网站建设论坛排名
  • 网站建设与推广方式起名网站建设
  • 厦门网站建设网站制作网站广告推广价格
  • 网站建设费用计入哪个科目深圳网站建设工资
  • 大岭山镇网站建设公司软文是什么文章
  • 网站正在建设张雪峰谈电子商务
  • 网站建设中标签导航的特征小型广告公司简介
  • 广西省建设厅网站jquery特效网站
  • 做推文的网站创意设计绘画作品
  • 做响应式网站的体会长沙域名注册公司
  • 网站备案照片 多少钱网站怎么做网页游戏
  • 金坛区建设局网站中搜网站提交
  • 建站之星如何建网站html静态网页作业成品
  • 商城类网站用什么做珠海找工作哪个网站好
  • 宁波建站模板厂家太原企业网站排名
  • 厦门网站建设定制多少钱wordpress能用一个数据库
  • 找人做网站需要准备什么材料怎么建设自己淘宝网站首页
  • 汽车网站建设费用js怎么做网站
  • 四川万景建设工程有限公司网站做公司网站用什么系统
  • 长沙企业建站系统3d视频制作公司
  • 长沙的网站制作公司网站建设方案的需求分析
  • 电子商务网站发展建设论文网站开发需要经过的几个主要阶段
  • 建设网站外贸做网站必须会php吗