How to quickly implement the Go Http Server framework? Done in one article

藏色散人
Release: 2022-12-14 20:43:18
forward
4891 people have browsed it

This article will introduce you to the relevant knowledge about Golang and talk about how to quickly implement the Go Http Server framework. I hope it will be helpful to everyone.

If you want to use http server in Go, the easiest way is to use 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"))})
Copy after login

define handle func [Related recommendations: Go video tutorial]

type HandlerFunc func(ResponseWriter, *Request)

The http server implementation of the standard library is very simple. Open a port and register a handler## that implements HandlerFunc

#At the same time, the standard library also provides a method to completely take over the request

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"))
    }}
Copy after login
Define ServerHTTP

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)}
Copy after login
If we need to write an HTTP Server framework, then we need to implement this method, and at the same time net The input and output streams of /http are not very convenient. We also need packaging, plus a simple Route, and do not write Path in ServeHTTP.

Here is a brief summary

  • An Engine that implements ServeHTTP

  • A Context that wraps the original input and output stream of HTTP

  • A Route that implements route matching

Route For the sake of simplicity, Map is used for complete matching

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}
Copy after login
We write a Test Verify our Http Server

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

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

    app.Run()}
Copy after login
The Handle we package here uses the Return error mode. Compared with the standard library, which only writes but does not return, it avoids errors caused by forgetting to return after not writing, which is usually difficult. Discover.

An Http Server also needs a middleware function. The idea here is to store an array of handleFunc in the Engine, which supports external registration. When a request comes in, a new Ctx is created and the global HandleFunc in the Engine is Copy it to Ctx, and then use c.Next() to implement matryoshka-style calling.

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}
Copy after login
The implementation method is very simple. Here we verify whether it can support pre- and 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()}
Copy after login
Output:

=== RUN   TestHttp
A1
Hello
B1
Copy after login
It only takes 100 lines of code in total, so we will A simple Http Server has been implemented. You can see the source code of Gin for subsequent details. The main focus is on Route and the implementation of the prefix tree.

The above is the detailed content of How to quickly implement the Go Http Server framework? Done in one article. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:learnku.com
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template