Heim > Backend-Entwicklung > Golang > Wie ich Express-Go in Stunden geschrieben habe

Wie ich Express-Go in Stunden geschrieben habe

Patricia Arquette
Freigeben: 2024-10-20 06:14:02
Original
438 Leute haben es durchsucht

How I Wrote Express-Go in Hours

Wenn Sie jemals mit Web-Frameworks wie Express.js gearbeitet haben, wissen Sie, wie bequem und einfach sie zu verwenden sein können. Stellen Sie sich nun die Leichtigkeit von Go mit seiner Leistung und Robustheit vor. Nun, das hat mich motiviert, express-go zu entwickeln, ein von Express.js inspiriertes Mikro-Framework, und das Beste von allem: Ich habe es in 19 Stunden erstellt! Die Reise war intensiv, aber jede Sekunde wert. Lassen Sie mich Ihnen erzählen, wie alles passiert ist. Offizieller Repository-Link

die Idee

Alles begann damit, dass ich dachte: „Es wäre cool, etwas Einfaches wie Express.js zu haben, aber mit der Leistung von Go!“. Go ist bereits dafür bekannt, minimalistisch und leistungsstark zu sein, aber als es darum ging, Webserver zu schreiben, hatte ich das Gefühl, dass etwas einfacher zu verwendendes wie Express.js noch fehlte.

Anstatt mich zu beschweren, beschloss ich, mir die Hände schmutzig zu machen und etwas zu bewirken. Ich war fest entschlossen, ein Mikro-Framework zu erstellen, das es mir ermöglichen würde, Routen zu konfigurieren und HTTP-Anfragen und -Antworten schnell und einfach zu verarbeiten.

Der Beginn der Reise

Ich habe mit der Grundstruktur begonnen: einer Go-Anwendung, die HTTP-Anfragen abhören und je nach Route unterschiedliche Funktionen ausführen kann.

Erster Halt: Routen

Als erstes musste ich das Routing einrichten. Ich wünschte, es wäre möglich, Routen auf ähnliche Weise wie Express.js zu definieren, wo Sie eine URL und eine Funktion zur Verarbeitung dieser Route angeben.

Hier ist die Magie der Routen:

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)
}
Nach dem Login kopieren
Nach dem Login kopieren

Die Idee hier war einfach: Ich wollte eine Routenkarte (map[string]func), bei der der Schlüssel die URL und der Wert die Funktion war, die die Anfrage bearbeiten würde.

Die Magie des Hundeführers

Eines der Dinge, die mir an Express.js am besten gefallen haben, war die Benutzerfreundlichkeit von Routenhandlern. Deshalb habe ich die Idee übernommen, dass jede Route nur eine Funktion wäre, die zwei Parameter empfängt: die Anfrage und die Antwort. In Go ist das etwas aufwändiger, da die Standardbibliothek viel manuelle Arbeit erfordert, deshalb habe ich einige Abstraktionen geschrieben, um es einfacher zu machen.

Bearbeitung von Anfragen
HTTP-Anfragen in Go beinhalten viele Strukturen und Methoden, daher habe ich all dies in einer Struktur namens Request gekapselt, mit einigen praktischen Methoden zum Abrufen von Abfrageparametern, Headern und dem Anfragetext.

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
}
Nach dem Login kopieren
Nach dem Login kopieren

Anstatt mich jetzt direkt mit der http.Request zu befassen, kann ich Folgendes tun:

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

Das macht die Dinge viel übersichtlicher und besser lesbar!

Einfach antworten

Nach den Anfragen war es an der Zeit, das Versenden von Antworten zu vereinfachen. Die Antwort brauchte auch einen Hauch von Einfachheit, damit ich schnell Text oder JSONs senden konnte.

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)
}
Nach dem Login kopieren
Nach dem Login kopieren

Das Ergebnis

Am Ende dieser 19 Stunden Arbeit habe ich es geschafft, express-go zu erstellen: ein schnelles und benutzerfreundliches Mikro-Framework, bei dem das Konfigurieren von Routen und das Senden von Antworten so einfach ist wie Express.js, aber mit allem die Kraft und Leistung von Go.

Anwendungsbeispiel:

Hier ist ein vollständiges Beispiel dafür, wie alles zusammenpasst:

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
}
Nach dem Login kopieren
Nach dem Login kopieren

Einfach, sauber und auf den Punkt gebracht. Ich kann mit Stolz sagen, dass ich dies in weniger als einem Tag erstellen konnte, und das Coole daran ist, dass es genug Flexibilität für kleine Projekte bietet, ohne die Komplexität größerer Frameworks.

Abschließende Überlegung

Die Entwicklung des Express-Go in 19 Stunden war eine unterhaltsame und herausfordernde Reise. Ich habe mich darauf konzentriert, echte Probleme zu lösen, mit denen ich bei Go-Servern konfrontiert war, und versucht, alles so intuitiv wie möglich zu gestalten. Natürlich gibt es noch viel zu tun, aber es gibt jede Menge zum Spielen!

Wenn Sie neugierig sind, werfen Sie einen Blick auf den Code und tragen Sie gerne dazu bei. Schließlich ist es viel cooler, solche Tools zu erstellen, wenn wir den Prozess teilen können!

Wenn Sie mich jetzt entschuldigen würden, werde ich mir einen Kaffee holen... nach 19 Stunden habe ich es verdient, oder?

Das obige ist der detaillierte Inhalt vonWie ich Express-Go in Stunden geschrieben habe. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Neueste Artikel des Autors
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage