Maison >développement back-end >Golang >Comment implémenter rapidement le framework Go Http Server ? Fait en un seul article

Comment implémenter rapidement le framework Go Http Server ? Fait en un seul article

藏色散人
藏色散人avant
2022-12-13 16:55:454959parcourir

Cet article vous présentera les connaissances pertinentes sur Golang et expliquera comment implémenter rapidement le framework Go Http Server. J'espère qu'il vous sera utile.

Si vous souhaitez utiliser le serveur http dans Go, le moyen le plus simple est d'utiliser http/net

err := http.ListenAndServe(":8080", nil)if err != nil {
    panic(err.Error())}http.HandleFunc("/hello", func(writer http.ResponseWriter, request *http.Request) {
    writer.Write([]byte("Hello"))})

pour définir la fonction handle [Recommandations associées : Tutoriel vidéo Go]

tapez HandlerFunc func(ResponseWriter, * Request) code><code>type HandlerFunc func(ResponseWriter, *Request)

标准库的 http 服务器实现很简单,开启一个端口,注册一个实现HandlerFunc

L'implémentation du serveur http de la bibliothèque standard est très simple. Ouvrez un port et enregistrez un gestionnaire qui implémente HandlerFunc

En même temps, la bibliothèque standard fournit également un. méthode pour reprendre complètement la requête

func main() {
    err := http.ListenAndServe(":8080", &Engine{})
    if err != nil {
        panic(err.Error())
    }}type Engine struct {}func (e *Engine) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path == "/hello" {
        w.Write([]byte("Hello"))
    }}
Define ServerHTTP

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)}
Si nous devons écrire un framework de serveur HTTP, alors nous devons implémenter cette méthode en même temps, les flux d'entrée et de sortie de net/http ne sont pas très. pratique. Nous avons également besoin d'un packaging, ainsi que d'un simple Route. N'écrivez pas Path dans ServeHTTP.

Voici un bref résumé
  • Un moteur qui implémente ServeHTTP
  • Un contexte qui enveloppe le flux d'entrée et de sortie HTTP d'origine
  • Une route qui implémente la correspondance de route

Route Pour plus de simplicité, Map est utilisé ici. Pour faire une correspondance complète

import (
    "net/http")type Engine struct {
    addr  string
    route map[string]handFunc}type Context struct {
    w      http.ResponseWriter
    r      *http.Request
    handle handFunc}type handFunc func(ctx *Context) errorfunc NewServer(addr string) *Engine {
    return &Engine{
        addr:  addr,
        route: make(map[string]handFunc),
    }}func (e *Engine) Run() {
    err := http.ListenAndServe(e.addr, e)
    if err != nil {
        panic(err)
    }}func (e *Engine) Get(path string, handle handFunc) {
    e.route[path] = handle}func (e *Engine) handle(writer http.ResponseWriter, request *http.Request, handle handFunc) {
    ctx := &Context{
        w:      writer,
        r:      request,
        handle: handle,
    }
    ctx.Next()}func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    handleF := e.route[req.URL.Path]
    e.handle(w, req, handleF)}func (c *Context) Next() error {
    return c.handle(c)}func (c *Context) Write(s string) error {
    _, err := c.w.Write([]byte(s))
    return err}
Nous écrivons un test pour vérifier notre serveur Http

func TestHttp(t *testing.T) {
    app := NewServer(":8080")

    app.Get("/hello", func(ctx *Context) error {
        return ctx.Write("Hello")
    })

    app.Run()}
Le handle que nous emballons ici utilise le mode d'erreur de retour. Par rapport à la bibliothèque standard, il écrit uniquement mais ne renvoie pas This. évite le problème de l'oubli de retour après ne pas avoir écrit des erreurs, souvent difficiles à repérer.

Un serveur HTTP a également besoin d'une fonction middleware. L'idée ici est de stocker un tableau de handleFunc dans le moteur, de prendre en charge l'enregistrement externe, de créer un nouveau Ctx lorsqu'une demande arrive et de copier le HandleFunc global dans le moteur vers le Ctx. , puis utilisez c.Next() pour implémenter les appels de style matriochka.

package httpimport (
    "net/http")type Engine struct {
    addr        string
    route       map[string]handFunc
    middlewares []handFunc}type Context struct {
    w        http.ResponseWriter
    r        *http.Request
    index    int
    handlers []handFunc}type handFunc func(ctx *Context) errorfunc NewServer(addr string) *Engine {
    return &Engine{
        addr:        addr,
        route:       make(map[string]handFunc),
        middlewares: make([]handFunc, 0),
    }}func (e *Engine) Run() {
    err := http.ListenAndServe(e.addr, e)
    if err != nil {
        panic(err)
    }}func (e *Engine) Use(middleware handFunc) {
    e.middlewares = append(e.middlewares, middleware)}func (e *Engine) Get(path string, handle handFunc) {
    e.route[path] = handle}func (e *Engine) handle(writer http.ResponseWriter, request *http.Request, handle handFunc) {
    handlers := make([]handFunc, 0, len(e.middlewares)+1)
    handlers = append(handlers, e.middlewares...)
    handlers = append(handlers, handle)
    ctx := &Context{
        w:        writer,
        r:        request,
        index:    -1,
        handlers: handlers,
    }
    ctx.Next()}func (e *Engine) ServeHTTP(w http.ResponseWriter, req *http.Request) {
    handleF := e.route[req.URL.Path]
    e.handle(w, req, handleF)}func (c *Context) Next() error {
    c.index++
    if c.index < len(c.handlers) {
        return c.handlers[c.index](c)
    }
    return nil}func (c *Context) Write(s string) error {
    _, err := c.w.Write([]byte(s))
    return err}
La méthode d'implémentation est très simple. Ici, nous vérifions si elle peut prendre en charge le pré- et le post-middleware

func TestHttp(t *testing.T) {
    app := NewServer(":8080")

    app.Get("/hello", func(ctx *Context) error {
        fmt.Println("Hello")
        return ctx.Write("Hello")
    })
    app.Use(func(ctx *Context) error {
        fmt.Println("A1")
        return ctx.Next()
    })
    app.Use(func(ctx *Context) error {
        err := ctx.Next()
        fmt.Println("B1")
        return err    })

    app.Run()}
Sortie :

=== RUN   TestHttp
A1
Hello
B1
Avec seulement 100 lignes de code au total, nous avons implémenté un simple serveur HTTP. allez aux détails de suivi En regardant le code source de Gin, l'accent est mis sur Route et l'implémentation de l'arborescence des préfixes. 🎜

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!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer