Maison > développement back-end > Golang > le corps du texte

Comment j'ai écrit Express-Go en quelques heures

Patricia Arquette
Libérer: 2024-10-20 06:14:02
original
342 Les gens l'ont consulté

How I Wrote Express-Go in Hours

Si vous avez déjà travaillé avec des frameworks Web comme Express.js, vous savez à quel point ils peuvent être pratiques et faciles à utiliser. Imaginez maintenant cette simplicité dans Go, avec ses performances et sa robustesse. Eh bien, cela m'a motivé à créer express-go, un micro-framework inspiré d'Express.js, et le meilleur de tout : je l'ai construit en 19 heures ! Le voyage a été intense, mais chaque seconde en valait la peine. Laissez-moi vous raconter comment tout cela s'est passé. Lien du référentiel officiel

l'idée

Tout a commencé quand j'ai pensé : "Ce serait cool d'avoir quelque chose de simple comme Express.js, mais avec les performances de Go !". Go est déjà connu pour être minimaliste et performant, mais lorsqu'il s'agissait d'écrire des serveurs Web, j'avais l'impression qu'il manquait encore quelque chose de plus facile à utiliser comme Express.js.

Alors au lieu de me plaindre, j'ai décidé de me salir les mains et de faire bouger les choses. J'étais déterminé à créer un micro-framework qui me permettrait de configurer des routes, de gérer les requêtes et les réponses HTTP rapidement et facilement.

Le début du voyage

J'ai commencé avec la structure de base : une application Go qui pouvait écouter les requêtes HTTP et, selon le parcours, remplir différentes fonctions.

Premier arrêt : itinéraires

La première chose que je devais faire était de configurer le routage. J'aurais aimé qu'il soit possible de définir des itinéraires de la même manière qu'Express.js, où vous spécifiez une URL et une fonction pour gérer cet itinéraire.

Voici la magie des itinéraires :

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)
}
Copier après la connexion
Copier après la connexion

L'idée ici était simple : je voulais une feuille de route (map[string]func) où la clé était l'URL et la valeur était la fonction qui gérerait la requête.

La magie du gestionnaire

L'une des choses que j'ai le plus appréciées dans Express.js était la facilité d'utilisation des gestionnaires de routes. J'ai donc adopté l'idée que chaque route serait juste une fonction qui recevrait deux paramètres : la requête et la réponse. Dans Go, c'est un peu plus de travail, car la bibliothèque standard nécessite beaucoup de travail manuel, j'ai donc écrit quelques abstractions pour faciliter les choses.

Traitement des demandes
Les requêtes HTTP dans Go impliquent de nombreuses structures et méthodes, j'ai donc encapsulé tout cela dans une structure appelée Request, avec des méthodes pratiques pour obtenir les paramètres de requête, les en-têtes et le corps de la requête.

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
}
Copier après la connexion
Copier après la connexion

Maintenant, au lieu de traiter directement la http.Request, je peux faire quelque chose comme :

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

Cela rend les choses beaucoup plus propres et plus lisibles !

Répondre facilement

Après les demandes, il était temps de faciliter l'envoi des réponses. La réponse avait également besoin d'une touche de simplicité pour que je puisse envoyer rapidement du texte ou des 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)
}
Copier après la connexion
Copier après la connexion

Le résultat

Au terme de ces 19 heures de travail, j'ai réussi à créer express-go : un micro-framework rapide et facile à utiliser, où configurer les itinéraires et envoyer des réponses est aussi simple qu'Express.js, mais avec tout la puissance et les performances du Go.

Exemple d'utilisation :

Voici un exemple complet de la façon dont tout cela s'articule :

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
}
Copier après la connexion
Copier après la connexion

Simple, propre et pertinent. Je suis fier de dire que j'ai pu construire cela en moins d'une journée, et ce qui est cool, c'est qu'il offre suffisamment de flexibilité pour les petits projets, sans toute la complexité des frameworks plus grands.

Réflexion finale

Créer l'express-go en 19 heures a été un voyage amusant et stimulant. Je me suis concentré sur la résolution des problèmes réels auxquels j'ai été confronté avec les serveurs Go et j'ai essayé de rendre tout aussi intuitif que possible. Bien sûr, il y a encore du travail à faire, mais il y a de quoi jouer !

Si vous êtes curieux, jetez un œil au code et n'hésitez pas à contribuer. Après tout, créer des outils comme celui-ci est bien plus cool lorsque nous pouvons partager le processus !

Maintenant, si tu veux bien m'excuser, je vais prendre un café... après 19 heures, je le mérite, non ?

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!