中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁 > news >正文

南京做網(wǎng)站外包省委副書記

南京做網(wǎng)站外包,省委副書記,傳統(tǒng)生意轉(zhuǎn)型做那個網(wǎng)站好,網(wǎng)站建設(shè)找哪些平臺通過go語言原生http中響應(yīng)錯誤的實現(xiàn)方法,逐步了解和使用微服務(wù)框架 kratos 的錯誤處理方式,以及探究其實現(xiàn)原理。 一、go原生http響應(yīng)錯誤信息的處理方法 處理方法: ①定義返回錯誤信息的結(jié)構(gòu)體 ErrorResponse // 定義http返回錯誤信息的…

?通過go語言原生http中響應(yīng)錯誤的實現(xiàn)方法,逐步了解和使用微服務(wù)框架 kratos 的錯誤處理方式,以及探究其實現(xiàn)原理。

一、go原生http響應(yīng)錯誤信息的處理方法

  • 處理方法:

①定義返回錯誤信息的結(jié)構(gòu)體 ErrorResponse

// 定義http返回錯誤信息的結(jié)構(gòu)體
type ErrorResponse struct {Code    int    `json:"code"`Message string `json:"message"`
}

②根據(jù)業(yè)務(wù)邏輯,為結(jié)構(gòu)體賦值相應(yīng)的錯誤信息

//這里為了簡化函數(shù),不進(jìn)行業(yè)務(wù)邏輯判斷,而直接返回錯誤信息
er := &ErrorResponse{Code:    403,Message: "用戶名不能為空",
}

③將錯誤信息序列化,并寫入到?http.ResponseWriter 中

// 設(shè)置響應(yīng)頭為JSON類型
w.Header().Set("Content-Type", "application/json")// 設(shè)置響應(yīng)狀態(tài)碼為400
w.WriteHeader(http.StatusBadRequest)// 將ErrorResponse轉(zhuǎn)換為JSON并寫入響應(yīng)體
//json.NewEncoder(w).Encode(he)//將錯誤信息結(jié)構(gòu)體序列化,并返回
res, _ := json.Marshal(er)
w.Write(res)

  • 代碼示例:
package mainimport ("encoding/json""net/http"
)// 定義http返回錯誤信息的結(jié)構(gòu)體
type ErrorResponse struct {Code    int    `json:"code"`Message string `json:"message"`
}func Login(w http.ResponseWriter, r *http.Request) {//這里為了簡化函數(shù),不進(jìn)行業(yè)務(wù)邏輯判斷,而直接返回錯誤信息er := &ErrorResponse{Code:    403,Message: "用戶名不能為空",}// 設(shè)置響應(yīng)頭為JSON類型w.Header().Set("Content-Type", "application/json")// 設(shè)置響應(yīng)狀態(tài)碼為400w.WriteHeader(http.StatusBadRequest)// 將ErrorResponse轉(zhuǎn)換為JSON并寫入響應(yīng)體//json.NewEncoder(w).Encode(he)//將錯誤信息結(jié)構(gòu)體序列化,并返回res, _ := json.Marshal(er)w.Write(res)
}func main() {//創(chuàng)建一個 HTTP 請求路由器mux := http.NewServeMux()mux.Handle("/login", http.HandlerFunc(Login))http.ListenAndServe(":8081", mux)
}
  • 效果演示:

二、微服務(wù)框架kratos響應(yīng)錯誤的方式

Kratos官網(wǎng)有關(guān)錯誤處理的介紹:錯誤處理 | Kratos

Kratos 有關(guān)錯誤處理的 examples 代碼見:examples/errors?、examples/http/errors

1、kratos默認(rèn)的錯誤信息格式
  • kratos響應(yīng)錯誤信息的默認(rèn)JSON格式為:
{// 錯誤碼,跟 http-status 一致,并且在 grpc 中可以轉(zhuǎn)換成 grpc-status"code": 500,// 錯誤原因,定義為業(yè)務(wù)判定錯誤碼"reason": "USER_NOT_FOUND",// 錯誤信息,為用戶可讀的信息,可作為用戶提示內(nèi)容"message": "invalid argument error",// 錯誤元信息,為錯誤添加附加可擴(kuò)展信息"metadata": {"foo": "bar"}
}
  • 使用方法:

①導(dǎo)入 kratos 的 errors 包

import "github.com/go-kratos/kratos/v2/errors"

②在業(yè)務(wù)邏輯中需要響應(yīng)錯誤時,用 New 方法生成錯誤信息(或通過 proto 生成的代碼響應(yīng)錯誤)

注意:這里的 New 方法是 Kratos 框架中的 errros.New,而不是 go 原生的 errors.New

func NewLoginRequest(username, password string) (*LoginRequest, error) {// 校驗參數(shù)if username == "" {//通過 New 方法創(chuàng)建一個錯誤信息err := errors.New(500, "USER_NAME_EMPTY", "用戶名不能為空")// 傳遞metadataerr = err.WithMetadata(map[string]string{ "remark": "請求參數(shù)中的 phone 字段為空",})return nil, err}if password == "" {// 通過 proto 生成的代碼響應(yīng)錯誤,并且包名應(yīng)替換為自己生成代碼后的 package name      return nil, api.ErrorPasswordIsEmpty("密碼不能為空")}return &LoginRequest{username: username,password: password,}, nil
}
  • 返回結(jié)果:

2、自定義錯誤信息格式

如果不想使用 kratos 默認(rèn)的錯誤響應(yīng)格式,可以自定義錯誤信息處理格式,方法如下:

①自定義錯誤信息結(jié)構(gòu)體

type HTTPError struct {Code     int    `json:"code"`Message  string `json:"message"`MoreInfo string `json:"moreInfo"`
}

②實現(xiàn)?FromError、errorEncoder 等方法

func (e *HTTPError) Error() string {return fmt.Sprintf("HTTPError code: %d message: %s", e.Code, e.Message)
}// FromError try to convert an error to *HTTPError.
func FromError(err error) *HTTPError {if err == nil {return nil}if se := new(HTTPError); errors.As(err, &se) {return se}return &HTTPError{Code: 500}
}func errorEncoder(w stdhttp.ResponseWriter, r *stdhttp.Request, err error) {se := FromError(err)codec, _ := http.CodecForRequest(r, "Accept")body, err := codec.Marshal(se)if err != nil {w.WriteHeader(500)return}w.Header().Set("Content-Type", "application/"+codec.Name())w.WriteHeader(se.Code)_, _ = w.Write(body)
}

③創(chuàng)建 http.Server 時,使用函數(shù) http.ErrorEncoder()?將上述?errorEncoder 添加到 ServerOption 中

httpSrv := http.NewServer(http.Address(":8000"),http.ErrorEncoder(errorEncoder),
)

④業(yè)務(wù)邏輯中需要響應(yīng)錯誤的地方返回自定義消息對象

return &HTTPError{Code: 400, Message: "用戶名不存在", MoreInfo: "請求參數(shù)中 userName = 張三"}
  • 完整代碼示例為:
package mainimport ("errors""fmt""log"stdhttp "net/http""github.com/go-kratos/kratos/v2""github.com/go-kratos/kratos/v2/transport/http"
)// HTTPError is an HTTP error.
type HTTPError struct {Code     int    `json:"code"`Message  string `json:"message"`MoreInfo string `json:"moreInfo"`
}func (e *HTTPError) Error() string {return fmt.Sprintf("HTTPError code: %d message: %s", e.Code, e.Message)
}// FromError try to convert an error to *HTTPError.
func FromError(err error) *HTTPError {if err == nil {return nil}if se := new(HTTPError); errors.As(err, &se) {return se}return &HTTPError{Code: 500}
}func errorEncoder(w stdhttp.ResponseWriter, r *stdhttp.Request, err error) {se := FromError(err)codec, _ := http.CodecForRequest(r, "Accept")body, err := codec.Marshal(se)if err != nil {w.WriteHeader(500)return}w.Header().Set("Content-Type", "application/"+codec.Name())w.WriteHeader(se.Code)_, _ = w.Write(body)
}func main() {httpSrv := http.NewServer(http.Address(":8082"),http.ErrorEncoder(errorEncoder),)router := httpSrv.Route("/")router.GET("login", func(ctx http.Context) error {return &HTTPError{Code: 400, Message: "用戶名不存在", MoreInfo: "請求參數(shù)中 userName = 張三"}})app := kratos.New(kratos.Name("mux"),kratos.Server(httpSrv,),)if err := app.Run(); err != nil {log.Fatal(err)}
}
  • 返回結(jié)果:

3、kratos返回錯誤信息JSON的源碼探究

至此,了解了 go 原生 http 和微服務(wù)框架 kratos 響應(yīng)錯誤信息的處理方式,對比可發(fā)現(xiàn):

①在原生http響應(yīng)處理中,我們先將錯誤消息結(jié)構(gòu)體序列化 res, _ := json.Marshal(er),然后通過?http.ResponseWriter.Write(res) 寫入錯誤信息JSON并返回

②在 kratos 中,我們在業(yè)務(wù)處理函數(shù)中僅僅通過?return errors.New() 返回了一個 error,并沒有將其序列化,但整個http請求卻返回了一個有關(guān)錯誤信息的 json 字符串

是什么原因呢?原來是 kratos 框架內(nèi)部完成了將錯誤信息結(jié)構(gòu)體序列化并寫入http.ResponseWriter的過程。

具體實現(xiàn)方式如下:

  • http server 結(jié)構(gòu)體 Server 中含有一個字段 ene?EncodeErrorFunc,專門用來進(jìn)行錯誤處理
//http/server.go
// Server is an HTTP server wrapper.
type Server struct {*http.Serverlis         net.ListenertlsConf     *tls.Configendpoint    *url.URLerr         errornetwork     stringaddress     stringtimeout     time.Durationfilters     []FilterFuncmiddleware  matcher.MatcherdecVars     DecodeRequestFuncdecQuery    DecodeRequestFuncdecBody     DecodeRequestFuncenc         EncodeResponseFuncene         EncodeErrorFunc           // 用于錯誤處理strictSlash boolrouter      *mux.Router
}//http/codec.go
// EncodeErrorFunc is encode error func.
type EncodeErrorFunc func(http.ResponseWriter, *http.Request, error)
  • 使用 NewServer() 創(chuàng)建時 http Server 時,ene 屬性會默認(rèn)為?DefaultErrorEncoder,該函數(shù)會將序列化錯誤信息,并寫入到?http.ResponseWriter 中
//http/server.go
// NewServer creates an HTTP server by options.
func NewServer(opts ...ServerOption) *Server {srv := &Server{network:     "tcp",address:     ":0",timeout:     1 * time.Second,middleware:  matcher.New(),decVars:     DefaultRequestVars,decQuery:    DefaultRequestQuery,decBody:     DefaultRequestDecoder,enc:         DefaultResponseEncoder,ene:         DefaultErrorEncoder,     //默認(rèn)的錯誤處理函數(shù)strictSlash: true,router:      mux.NewRouter(),}for _, o := range opts {o(srv)}srv.router.StrictSlash(srv.strictSlash)srv.router.NotFoundHandler = http.DefaultServeMuxsrv.router.MethodNotAllowedHandler = http.DefaultServeMuxsrv.router.Use(srv.filter())srv.Server = &http.Server{Handler:   FilterChain(srv.filters...)(srv.router),TLSConfig: srv.tlsConf,}return srv
}//http/codec.go
// DefaultErrorEncoder encodes the error to the HTTP response.
func DefaultErrorEncoder(w http.ResponseWriter, r *http.Request, err error) {se := errors.FromError(err)codec, _ := CodecForRequest(r, "Accept")body, err := codec.Marshal(se)    //序列化錯誤信息結(jié)構(gòu)體if err != nil {w.WriteHeader(http.StatusInternalServerError)return}w.Header().Set("Content-Type", httputil.ContentType(codec.Name()))w.WriteHeader(int(se.Code))_, _ = w.Write(body)            //將序列化的結(jié)果寫入到響應(yīng)中
}
  • 路由處理函數(shù) router.GET() 等會調(diào)用 Router.Handle,?其中會判斷 HandlerFunc 是否有返回錯誤,如果有,則會調(diào)用 server.ene 函數(shù),從而完成錯誤信息序列化并返回
//main.go
func main() {httpSrv := http.NewServer(http.Address(":8082"),)router := httpSrv.Route("/")router.GET("login", func(ctx http.Context) error {return errors.New(500, "USER_NOT_FOUND", "用戶名不存在")})
}//http/router.go
// GET registers a new GET route for a path with matching handler in the router.
func (r *Router) GET(path string, h HandlerFunc, m ...FilterFunc) {r.Handle(http.MethodGet, path, h, m...)
}//http/router.go
// Handle registers a new route with a matcher for the URL path and method.
func (r *Router) Handle(method, relativePath string, h HandlerFunc, filters ...FilterFunc) {next := http.Handler(http.HandlerFunc(func(res http.ResponseWriter, req *http.Request) {ctx := r.pool.Get().(Context)ctx.Reset(res, req)//重點:這里判斷路由處理函數(shù)是否返回了 error,如果是,則調(diào)用 server.ene 函數(shù),序列化錯誤信息并返回if err := h(ctx); err != nil {r.srv.ene(res, req, err)}ctx.Reset(nil, nil)r.pool.Put(ctx)}))next = FilterChain(filters...)(next)next = FilterChain(r.filters...)(next)r.srv.router.Handle(path.Join(r.prefix, relativePath), next).Methods(method)
}
  • 自定義錯誤消息結(jié)構(gòu)體后,創(chuàng)建 http server 時,通過 http.ErrorEncoder(errorEncoder) 將自定義的錯誤處理函數(shù)賦值給 server.ene,替換了默認(rèn)的?DefaultErrorEncoder
// main.go
//自定義的錯誤處理函數(shù)
func errorEncoder(w stdhttp.ResponseWriter, r *stdhttp.Request, err error) {se := FromError(err)codec, _ := http.CodecForRequest(r, "Accept")body, err := codec.Marshal(se)if err != nil {w.WriteHeader(500)return}w.Header().Set("Content-Type", "application/"+codec.Name())w.WriteHeader(se.Code)_, _ = w.Write(body)
}// main.go
func main() {httpSrv := http.NewServer(http.Address(":8082"),http.ErrorEncoder(errorEncoder),  // 將自定義的錯誤處理函數(shù)賦值給 sever)
}// http/server.go
// ErrorEncoder with error encoder.
func ErrorEncoder(en EncodeErrorFunc) ServerOption {return func(o *Server) {o.ene = en}
}

http://www.risenshineclean.com/news/10911.html

相關(guān)文章:

  • 網(wǎng)站建設(shè)指導(dǎo)全國seo公司排名
  • 網(wǎng)站標(biāo)題正確書寫標(biāo)準(zhǔn)百度q3財報2022
  • 國外素材網(wǎng)站博客可以做seo嗎
  • 做網(wǎng)站怎么宣傳百度推廣怎么收費標(biāo)準(zhǔn)
  • 鄭州網(wǎng)絡(luò)重慶seo俱樂部聯(lián)系方式
  • 河南平安建設(shè)網(wǎng)站上海網(wǎng)站建設(shè)聯(lián)系方式
  • 鞏義網(wǎng)站建設(shè)方案書營銷網(wǎng)絡(luò)營銷
  • 網(wǎng)站banner特效近三天發(fā)生的重要新聞
  • 網(wǎng)站主機(jī)空間企業(yè)網(wǎng)站模板html
  • 聊城建設(shè)工程質(zhì)量信息網(wǎng)站廣州網(wǎng)站排名優(yōu)化公司
  • 個人注冊的網(wǎng)站可以做公司宣傳用嗎谷歌app官方下載
  • 大豐做網(wǎng)站seo排名優(yōu)化方式方法
  • 花都營銷型網(wǎng)站高效統(tǒng)籌疫情防控和經(jīng)濟(jì)社會發(fā)展
  • 中國十大搜索引擎網(wǎng)站網(wǎng)站推廣工具有哪些
  • python做網(wǎng)站的案例微信朋友圈推廣平臺
  • 網(wǎng)站建設(shè) 驗收意見成人廚師短期培訓(xùn)班
  • 四川城鄉(xiāng)建設(shè)部網(wǎng)站首頁百度app推廣
  • seo網(wǎng)站編輯什么是搜索引擎銷售
  • 怎么制作公司自己網(wǎng)站黃頁網(wǎng)絡(luò)的推廣網(wǎng)站有哪些
  • 利用社交網(wǎng)站做淘寶客國內(nèi)看不到的中文新聞網(wǎng)站
  • 手機(jī)產(chǎn)品展示網(wǎng)站模板百度推廣案例及效果
  • 江蘇建設(shè)教育協(xié)會網(wǎng)站免費輿情網(wǎng)站下載大全最新版
  • 廣州專業(yè)做網(wǎng)站建設(shè)淘寶運營培訓(xùn)班
  • 怎樣建立自己網(wǎng)站視頻網(wǎng)站小紅書如何引流推廣
  • 做網(wǎng)站推廣有前景嗎站內(nèi)推廣和站外推廣的區(qū)別
  • 免費網(wǎng)頁設(shè)計生成器關(guān)于進(jìn)一步優(yōu)化
  • 網(wǎng)站規(guī)劃書 確定網(wǎng)站建設(shè)目的新聞?wù)?022最新20篇
  • 怎樣給自己的網(wǎng)站做優(yōu)化湖南百度推廣
  • 淳安縣建設(shè)局網(wǎng)站網(wǎng)站優(yōu)化方案案例
  • 網(wǎng)站開發(fā)移動app寧波seo怎么推廣