Go Gin source learning

Main process implementation of Gin routing

After the previous learning notes, we have known the main process of Gin router. But we can see that the code and method body are very long, most of them are the judgment of parameter routing. These scattered little logic, let us read the source code more difficult to understand some. But in fact, the logic of the base tree is not so complicated, so we implement the following simple base tree value including the main process according to the old rules. The code is as follows:

package mygin

import "fmt"

type Trees map[string]*node

type node struct {
    path     string
    indices  string
    children []*node
    handlers HandlerList
}

func (n *node) addRoute(path string, handlers HandlerList) {
    if len(n.path) > 0 || len(n.children) > 0 {
    walk:
        for {
            //Find the equivalent index
            i := 0
            max := min(len(path), len(n.path))
            for max > i && path[i] == n.path[i] {
                i++
            }
            //You need to put the original as a child node into the new node
            if i < len(n.path) {
                //New node
                child := node{
                    path:     n.path[i:],
                    indices:  n.indices,
                    handlers: n.handlers,
                    children: n.children,
                }

                n.children = []*node{&child}
                n.indices = string([]byte{n.path[i]})
                n.path = path[:i]
                n.handlers = nil
            }
            // Judge if the child node has the same beginning character, it will jump into the loop again
            if i < len(path) {
                c := path[i]
                for index := 0; index < len(n.indices); index++ {
                    if c == n.indices[index] {
                        n = n.children[index]
                        path = path[i:]
                        continue walk
                    }
                }

                //Add the path of the new request to the router
                n.insertChild(path[i:], path, handlers, i)
                return
            }
            return
        }
    } else {
        //If it is empty
        n.path = path
        n.handlers = handlers
    }
}

func (n *node) insertChild(path, fullPath string, handlers HandlerList, index int) {
    child := node{}
    child.handlers = handlers
    child.indices = ""
    child.path = path
    n.indices += string([]byte{fullPath[index]})
    n.children = append(n.children, &child)
}

func min(a, b int) int {
    if a > b {
        return b
    }

    return a
}

func (n *node) getValue(path string) (handlers HandlerList) {
    index := 1
walk:
    for {
        fmt.Println("loop num: ", index)
        if len(path) > len(n.path) {
            path = path[len(n.path):]
            c := path[0]
            for i := 0; i < len(n.indices); i++ {
                if c == n.indices[i] {
                    n = n.children[i]
                    index++
                    goto walk
                }
            }
        } else if len(path) == len(n.path) {
            handlers = n.handlers
            return
        }
    }
}

summary

The above code does not need too many comments. The whole process of code without parameter nodes is very clear.

Concluding remarks

Gin's source code learning and analysis are all over. In fact, there have been many articles on the analysis of the source code of gin framework, but it will be more helpful for us to simply imitate and implement these functions while learning.
Gin is a very lightweight http framework, the code is also very brief and clear. There are also some highlights in the implementation. I think it is very suitable for beginners to learn and analyze the go source code. I hope these 5 articles can help people in learning go.

Tags: Go

Posted on Sun, 10 Nov 2019 14:10:07 -0500 by Jeller