Bu örnekte, HTTP işleyicilerinin kullanımını ve hata işlemeyi standartlaştırması için bir arabirim oluşturacağız. API çağrıları için hata ve yanıt işlemeyi basitleştirmeye yardımcı olacaktır. Örnek basit bit seviyede tutuldu, ancak onu geliştirmelisiniz, o nedenle olduğu gibi kabul etmeyin.


main.go


package main

import (
"log"

"random/http"
"random/users"
)

func main() {
rtr := http.NewRouter()
rtr.Add("/api/v1/users", users.Handler)

srv := http.NewServer(rtr.Handler, ":3000")
log.Fatal(srv.ListenAndServe())
}

http/server.go


package http

import (
"net/http"
)

func NewServer(handler http.Handler, address string) *http.Server {
return &http.Server{
Handler: handler,
Addr: address,
}
}


http/router.go


package http

import "net/http"

type Router struct {
Handler *http.ServeMux
}

func NewRouter() *Router {
return &Router{
Handler: http.NewServeMux(),
}
}

func (r *Router) Add(path string, hnd handler) {
r.Handler.Handle(path, handler(hnd))
}

http/handler.go


package http

import (
"errors"
"fmt"
"net/http"
)

type handler func(http.ResponseWriter, *http.Request) error

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
err := h(w, r)
if err == nil {
return
}

var e Error
if !errors.As(err, &e) {
w.WriteHeader(http.StatusInternalServerError)
return
}

w.WriteHeader(e.Status)
w.Write([]byte(fmt.Sprintf("code: %s, message: %s", e.Code, e.Error())))
}

http/error.go


package http

type Error struct {
Status int
Code string
Message string
}

func (e Error) Error() string {
return e.Message
}

domain/error.go


package domain

import "random/http"

var (
ErrInternalError = http.Error{Status: 500, Code: "internal_error", Message: "An internal error has occurred"}
ErrInvalidRequest = http.Error{Status: 400, Code: "invalid_request", Message: "Request is invalid"}
ErrResourceConflict = http.Error{Status: 409, Code: "resource_conflict", Message: "A resource conflict has been detected"}
ErrResourceNotFound = http.Error{Status: 404, Code: "resource_not_found", Message: "Resource is not found"}
)

users/api.go


package users

import (
"fmt"
"net/http"
"random/domain"
)

func Handler(w http.ResponseWriter, r *http.Request) error {
id := r.Header.Get("id")
if id == "" {
return domain.ErrInvalidRequest
}
if id == "0" {
return domain.ErrResourceNotFound
}
if id == "1" {
return domain.ErrResourceConflict
}

w.WriteHeader(http.StatusOK)
w.Write([]byte(fmt.Sprintf("I am user with id %s", id)))

return nil
}