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 중국어 웹사이트의 기타 관련 기사를 참조하세요!