>백엔드 개발 >Golang >몇 시간 만에 Express-Go를 작성하는 방법

몇 시간 만에 Express-Go를 작성하는 방법

Patricia Arquette
Patricia Arquette원래의
2024-10-20 06:14:02453검색

How I Wrote Express-Go in Hours

Express.js와 같은 웹 프레임워크로 작업해 본 적이 있다면 이것이 얼마나 편리하고 사용하기 쉬운지 알 것입니다. 이제 Go의 성능과 견고함을 상상해 보세요. 글쎄요, 이것이 제가 Express.js에서 영감을 받은 마이크로 프레임워크인 express-go를 만들도록 동기를 부여했으며 무엇보다도 가장 좋은 점은 19시간 만에 구축했다는 것입니다! 여행은 강렬했지만 매 순간의 가치가 있었습니다. 이 모든 일이 어떻게 일어났는지 말씀드리겠습니다. 공식 저장소 링크

아이디어

모든 것은 "Express.js처럼 간단한 것이 있으면 좋겠지만 Go!의 성능이 있으면 좋겠다"는 생각에서 시작되었습니다. Go는 이미 미니멀하고 성능이 뛰어난 것으로 알려져 있지만, 웹 서버를 작성할 때 Express.js와 같이 사용하기 쉬운 것이 아직 부족하다고 느꼈습니다.

그래서 불평보다는 손을 더럽히고 뭔가를 해보기로 했습니다. 저는 경로를 구성하고 HTTP 요청 및 응답을 빠르고 쉽게 처리할 수 있는 마이크로 프레임워크를 만들기로 결심했습니다.

여행의 시작

저는 HTTP 요청을 수신하고 경로에 따라 다양한 기능을 수행할 수 있는 Go 애플리케이션이라는 기본 구조부터 시작했습니다.

첫 번째 정류장: 경로

가장 먼저 해야 할 일은 경로 설정이었습니다. Express.js와 비슷한 방식으로 경로를 정의하여 URL과 해당 경로를 처리하는 함수를 지정할 수 있었으면 좋겠습니다.

경로의 마법은 다음과 같습니다.

type App struct {
    routes map[string]func(req *req.Request, res *req.Response)
}

func NewApp() *App {
    return &App{
        routes: make(map[string]func(req *req.Request, res *req.Response)),
    }
}

func (a *App) Route(path string, handler func(req *req.Request, res *req.Response)) {
    a.routes[path] = handler
}

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if handler, exists := a.routes[r.URL.Path]; exists {
        request := req.NewRequest(r)
        response := req.NewResponse(w)
        handler(request, response)
    } else {
        http.NotFound(w, r)
    }
}

func (a *App) Listen(addr string) error {
    return http.ListenAndServe(addr, a)
}

여기서 아이디어는 간단했습니다. 키가 URL이고 값이 요청을 처리할 함수인 경로 맵(map[string]func)을 원했습니다.

핸들러의 마법

Express.js에서 제가 가장 마음에 들었던 점 중 하나는 경로 핸들러를 사용하기 쉽다는 점이었습니다. 그래서 저는 각 경로가 요청과 응답이라는 두 가지 매개변수를 받는 함수일 뿐이라는 생각을 채택했습니다. Go에서는 표준 라이브러리에 많은 수동 작업이 필요하기 때문에 작업이 조금 더 필요하므로 이를 더 쉽게 하기 위해 몇 가지 추상화를 작성했습니다.

요청 처리
Go의 HTTP 요청에는 많은 구조와 메소드가 포함되므로 쿼리 매개변수, 헤더 및 요청 본문을 가져오기 위한 몇 가지 편리한 메소드와 함께 이 모든 것을 Request라는 구조에 캡슐화했습니다.

type Request struct {
    Req  *http.Request
    Body string
}

func NewRequest(req *http.Request) *Request {

    bodyBytes, _ := io.ReadAll(req.Body)
    bodyString := string(bodyBytes)

    return &Request{
        Req:  req,
        Body: bodyString,
    }
}

func (r *Request) QueryParam(key string) string {
    params := r.Req.URL.Query()
    return params.Get(key)
}

func (r *Request) Header(key string) string {
    return r.Req.Header.Get(key)
}

func (r *Request) BodyAsString() string {
    return r.Body
}

이제 http.Request를 직접 처리하는 대신 다음과 같은 작업을 수행할 수 있습니다.

app.Route("/greet", func(r *req.Request, w *req.Response) {
    name := r.QueryParam("name")
    if name == "" {
        name = "Guest"
    }
    w.Send("Hello, " + name + "!")
})

이렇게 하면 내용이 훨씬 깔끔하고 읽기 쉬워집니다!

응답하기 쉬움

요청 후에는 응답을 더 쉽게 보낼 수 있는 시간이 되었습니다. 응답에는 텍스트나 JSON을 빠르게 보낼 수 있는 단순함이 필요했습니다.

type App struct {
    routes map[string]func(req *req.Request, res *req.Response)
}

func NewApp() *App {
    return &App{
        routes: make(map[string]func(req *req.Request, res *req.Response)),
    }
}

func (a *App) Route(path string, handler func(req *req.Request, res *req.Response)) {
    a.routes[path] = handler
}

func (a *App) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if handler, exists := a.routes[r.URL.Path]; exists {
        request := req.NewRequest(r)
        response := req.NewResponse(w)
        handler(request, response)
    } else {
        http.NotFound(w, r)
    }
}

func (a *App) Listen(addr string) error {
    return http.ListenAndServe(addr, a)
}

결과

19시간의 작업 끝에 저는 경로를 구성하고 응답을 보내는 것이 Express.js만큼 간단하지만 모든 기능을 갖춘 빠르고 사용하기 쉬운 마이크로 프레임워크인 express-go를 만들었습니다. 바둑의 힘과 성능.

사용 예:

다음은 이 모든 것이 어떻게 조화를 이루는지에 대한 완전한 예입니다.

type Request struct {
    Req  *http.Request
    Body string
}

func NewRequest(req *http.Request) *Request {

    bodyBytes, _ := io.ReadAll(req.Body)
    bodyString := string(bodyBytes)

    return &Request{
        Req:  req,
        Body: bodyString,
    }
}

func (r *Request) QueryParam(key string) string {
    params := r.Req.URL.Query()
    return params.Get(key)
}

func (r *Request) Header(key string) string {
    return r.Req.Header.Get(key)
}

func (r *Request) BodyAsString() string {
    return r.Body
}

간단하고 깨끗하며 요점이 명확합니다. 하루도 안 돼서 이를 구축할 수 있었다는 것이 자랑스럽습니다. 멋진 점은 대규모 프레임워크의 복잡성 없이 소규모 프로젝트에 충분한 유연성을 제공한다는 것입니다.

최종 반영

19시간 만에 급행을 만드는 것은 재미있고 도전적인 여정이었습니다. 나는 Go 서버에서 직면했던 실제 문제를 해결하는 데 집중했고 모든 것을 가능한 한 직관적으로 만들려고 노력했습니다. 물론 해야 할 일이 더 많지만, 놀거리도 많습니다!

궁금하시면 코드를 보시고 자유롭게 참여해 주세요. 결국, 이와 같은 도구를 만드는 과정을 공유할 수 있으면 훨씬 더 멋질 것입니다!

이제 실례지만 커피 한잔... 19시간 후에는 그럴 자격이 있겠죠?

위 내용은 몇 시간 만에 Express-Go를 작성하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.