1、使用NewServer函数构建服务实例,利用依赖注入方式将所有的依赖参数包含进来。
func NewServer(
logger *Logger
config *Config
commentStore *commentStore
anotherStore *anotherStore
) http.Handler {
mux := http.NewServeMux()
addRoutes(
mux,
Logger,
Config,
commentStore,
anotherStore,
)
var handler http.Handler = mux
handler = someMiddleware(handler)
handler = someMiddleware2(handler)
handler = someMiddleware3(handler)
return handler
}
2、在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())
}
3、主函数只调用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)
}
}
4、返回闭包 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 request
logger.Info(r.Context(), "msg", "handleSomething")
}
)
}
5、定义通用的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 T
if err := json.NewDecoder(r.Body).Decode(&v); err != nil {
return v, fmt.Errorf("decode json: %w", err)
}
return v, nil
}
6、提供一个抽象的 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 T
if 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 接口。
7、使用 Once 延迟调用来提高启动性能。
func handleTemplate(files string...) http.HandlerFunc {
var (
init sync.Once
tpl *template.Template
tplerr 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
}
}
本文内容不用于商业目的,如涉及知识产权问题,请权利人联系51Testing小编(021-64471599-8017),我们将立即处理