技術閱讀周刊,每周更新。
歷史更新
20231122:第十一期
20231129:第十二期
20240105:第十三期:一些提高生產力的終端命令
20240112:第十四期:Golang 作者 Rob Pike 在 GopherConAU 上的分享
How I write HTTP services in Go after 13 years

使用NewServer函數構建服務實例,利用依賴注入方式將所有的依賴參數包含進來。
func?NewServer(logger?*Loggerconfig?*ConfigcommentStore?*commentStoreanotherStore?*anotherStore
)?http.Handler?{mux?:=?http.NewServeMux()addRoutes(mux,Logger,Config,commentStore,anotherStore,)var?handler?http.Handler?=?muxhandler?=?someMiddleware(handler)handler?=?someMiddleware2(handler)handler?=?someMiddleware3(handler)return?handler
}
在routes.go文件中統一定義所有路由函數。
func?addRoutes(mux?????????????????*http.ServeMux,logger??????????????*logging.Logger,config??????????????Config,tenantsStore????????*TenantsStore,commentsStore???????*CommentsStore,conversationService?*ConversationService,chatGPTService??????*ChatGPTService,authProxy???????????*authProxy
)?{mux.Handle("/api/v1/",?handleTenantsGet(logger,?tenantsStore))mux.Handle("/oauth2/",?handleOAuth2Proxy(logger,?authProxy))mux.HandleFunc("/healthz",?handleHealthzPlease(logger))mux.Handle("/",?http.NotFoundHandler())
}
主函數只調用run函數來運行服務
func?run(ctx?context.Context,?w?io.Writer,?args?[]string)?error?{ctx,?cancel?:=?signal.NotifyContext(ctx,?os.Interrupt)defer?cancel()//?...
}func?main()?{ctx?:=?context.Background()if?err?:=?run(ctx,?os.Stdout,?os.Args);?err?!=?nil?{fmt.Fprintf(os.Stderr,?"%s\n",?err)os.Exit(1)}
}
返回閉包 handle
//?handleSomething?handles?one?of?those?web?requests
//?that?you?hear?so?much?about.
func?handleSomething(logger?*Logger)?http.Handler?{thing?:=?prepareThing()return?http.HandlerFunc(func(w?http.ResponseWriter,?r?*http.Request)?{//?use?thing?to?handle?requestlogger.Info(r.Context(),?"msg",?"handleSomething")})
}
定義通用的encode和decode函數
func?encode[T?any](w?http.ResponseWriter,?r?*http.Request,?status?int,?v?T)?error?{w.Header().Set("Content-Type",?"application/json")w.WriteHeader(status)if?err?:=?json.NewEncoder(w).Encode(v);?err?!=?nil?{return?fmt.Errorf("encode?json:?%w",?err)}return?nil
}func?decode[T?any](r?*http.Request)?(T,?error)?{var?v?Tif?err?:=?json.NewDecoder(r.Body).Decode(&v);?err?!=?nil?{return?v,?fmt.Errorf("decode?json:?%w",?err)}return?v,?nil
}
提供一個抽象的 Validator 接口用于驗證
//?Validator?is?an?object?that?can?be?validated.
type?Validator?interface?{//?Valid?checks?the?object?and?returns?any//?problems.?If?len(problems)?==?0?then//?the?object?is?valid.Valid(ctx?context.Context)?(problems?map[string]string)
}func?decodeValid[T?Validator](r?*http.Request)?(T,?map[string]string,?error)?{var?v?Tif?err?:=?json.NewDecoder(r.Body).Decode(&v);?err?!=?nil?{return?v,?nil,?fmt.Errorf("decode?json:?%w",?err)}if?problems?:=?v.Valid(r.Context());?len(problems)?>?0?{return?v,?problems,?fmt.Errorf("invalid?%T:?%d?problems",?v,?len(problems))}return?v,?nil,?nil
}
自定義校驗需要實現 Validator
接口。
使用 Once 延遲調用來提高啟動性能。
func?handleTemplate(files?string...)?http.HandlerFunc?{var?(init????sync.Oncetpl?????*template.Templatetplerr??error)return?func(w?http.ResponseWriter,?r?*http.Request)?{init.Do(func(){tpl,?tplerr?=?template.ParseFiles(files...)})if?tplerr?!=?nil?{http.Error(w,?tplerr.Error(),?http.StatusInternalServerError)return}//?use?tpl}
}
What is OpenTelemetry?

這是一篇 OTel 的科普文章
OpenTelemetry 提供一個統一、可擴展的框架,用于收集、分析和觀察分布式系統的性能數據。它包括一組API、庫、代理和收集器,這些組件可以跨多種編程語言和平臺實現對應用程序的監控。
OpenTelemetry 整合 OpenTracing 和 OpenCensus。

2019年,兩個社區進行了合并。
同時 OTel 具備以下特征:
統一性:OpenTelemetry 提供了一個統一的API,使得開發者可以在不同的編程語言和框架中以一致的方式實現監控。
可擴展性:可以編寫自己的擴展來滿足個性化需要
跨平臺:OpenTelemetry 支持多種編程語言,如 Java、Python、Go、.NET 等,以及多種云服務和容器平臺。
社區驅動:作為一個開源項目,OpenTelemetry 由一個活躍的社區支持,社區成員貢獻代碼、文檔和最佳實踐。
與現有工具的兼容性:OpenTelemetry 設計時考慮了與現有監控工具的兼容性,如 Prometheus、Jaeger、Zipkin 等,這使得它可以輕松地集成到現有的監控基礎設施中。
提供了一種名為:OTLP(OpenTelemetry Protocol)的通訊協議,基于 gRPC。
使用該協議用于客戶端與 Collector 采集器進行交互。
Collector 是 OpenTelemetry 架構中的一個關鍵組件,它負責接收、處理和導出數據(Trace/log/metrics)。

它可以接受從客戶端發出的數據進行處理,同時可以導出為不同格式的數據。
總的來說 OTel 是可觀測系統的新標準,基于它可以兼容以前使用的 Prometheus、 victoriametrics、skywalking 等系統,同時還可以靈活擴展,不用與任何但一生態或技術棧進行綁定。
Popular git config options

本文總結了一些常用的 git 配置
pull.ff only
或pull.rebase true
:這兩個選項都可以避免在執行git pull
時意外創建合并提交,特別是當上游分支已經發生了變化的時候。merge.conflictstyle diff3
:這個選項使得合并沖突更易于閱讀,通過在沖突中顯示原始代碼版本,幫助用戶更好地解決沖突。rebase.autosquash true
和rebase.autostash true
:這些選項使得修改舊提交變得更容易,并且自動處理stash。push.default simple
或push.default current
:這些選項告訴git push
自動推送當前分支到同名的遠程分支。init.defaultBranch main
:創建新倉庫時,默認創建main
分支而不是master
分支。commit.verbose true
:在提交時顯示整個提交差異。rerere.enabled true
:啟用rerere
功能,自動解決沖突help.autocorrect
:設置自動矯正的級別,以自動運行建議的命令。core.pager delta
:設置Git使用的分頁器,例如使用delta
來查看帶有語法高亮的diff。diff.algorithm histogram
:設置Git的diff算法,以改善函數重排時的diff顯示。
文章鏈接:
https://grafana.com/blog/2024/02/09/how-i-write-http-services-in-go-after-13-years/
https://codeboten.medium.com/what-is-opentelemetry-6a7e5c6901c5
https://jvns.ca/blog/2024/02/16/popular-git-config-options/
往期推薦
【譯】Apache Pulsar 3.2.0 發布
我的 2023
手把手教你為開源項目貢獻代碼
得物云原生全鏈路追蹤Trace2.0架構實踐
點分享
點收藏
點點贊
點在看