// handleSomething handles one of those web requests // that you hear so much about. funchandleSomething(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") } ) }
定义通用的encode和decode函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
funcencode[Tany](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) } returnnil }
funcdecode[Tany](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 }
提供一个抽象的 Validator 接口用于验证
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// 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) }
funcdecodeValid[TValidator](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 接口。
使用 Once 延迟调用来提高启动性能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
funchandleTemplate(files string...) http.HandlerFunc { var ( init sync.Once tpl *template.Template tplerr error ) returnfunc(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 } }