Search code examples
gostructstateless

Struct value been stored in every request Golang using net/http


I am new to Golang, I am testing the net/http to run some path but I got some problem that I don't understand.

Here is my codes.

package main

import (
    "fmt"
    "net/http"  
)
type Content struct {
   Data map[interface{}]interface{}
}

func main() {
    mux := http.NewServeMux()

    mux.Handle("/favicon.ico", http.NotFoundHandler())
    mux.HandleFunc("/", Index)
    mux.HandleFunc("/test", Testhandler)
    http.ListenAndServe(":8080", mux)
}

func Index(w http.ResponseWriter, r *http.Request) {
    if r.URL.Path != "/" {
        fmt.Println("404");
        return
    }
    fmt.Println("index content ", Content)

}

func Testhandler(w http.ResponseWriter, r *http.Request) {

    data := make(map[interface{}]interface{})
    data["data1"] = "data 1 content"
    data["data2"] = "data 2 content"
    Content.Data = data
    fmt.Println("test content ", Content)

}

So, if I go to index http://localhost:8080/, I got empty content index content {{false } map[]} ,

And I goto http://localhost:8080/test I got the content correctly , test content {{false } map[data1:data 1 content data2:data 2 content]},

But when I go back to index http://localhost:8080/ there already content there index content {{false } map[data1:data 1 content data2:data 2 content]},

So question here, why am I not getting the empty struct content when I back to the index? I thought the struct will be in initial state with every single request? The http should be stateless, right?


Solution

  • What you are probably experiencing is the result of this code or something similar (your code does not compile):

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    var Content struct {
        Data map[interface{}]interface{}
    }
    
    func main() {
        mux := http.NewServeMux()
    
        mux.Handle("/favicon.ico", http.NotFoundHandler())
        mux.HandleFunc("/", Index)
        mux.HandleFunc("/test", Testhandler)
        http.ListenAndServe(":8080", mux)
    }
    
    func Index(w http.ResponseWriter, r *http.Request) {
        if r.URL.Path != "/" {
            fmt.Println("404")
            return
        }
        fmt.Println("index content ", Content)
    }
    
    func Testhandler(w http.ResponseWriter, r *http.Request) {
        data := make(map[interface{}]interface{})
        data["data1"] = "data 1 content"
        data["data2"] = "data 2 content"
        Content.Data = data
        fmt.Println("test content ", Content)
    }
    

    Solution

    With this you are creating a global variable Content that keeps its state across calls to the webserver. What you probably intended is this:

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    type Content struct {
        Data map[interface{}]interface{}
    }
    
    func main() {
        mux := http.NewServeMux()
    
        mux.Handle("/favicon.ico", http.NotFoundHandler())
        mux.HandleFunc("/", Index)
        mux.HandleFunc("/test", Testhandler)
        http.ListenAndServe(":8080", mux)
    }
    
    func Index(w http.ResponseWriter, r *http.Request) {
        var c Content
        if r.URL.Path != "/" {
            fmt.Println("404")
            return
        }
        fmt.Println("index content ", c)
    }
    
    func Testhandler(w http.ResponseWriter, r *http.Request) {
        var c Content
        data := make(map[interface{}]interface{})
        data["data1"] = "data 1 content"
        data["data2"] = "data 2 content"
        c.Data = data
        fmt.Println("test content ", c)
    }
    

    Changes made

    • make Content a type as you already did in your sample (that way it is not a global variable any more but defining a type we can reuse)
    • declare Content in each call where it is needed (not globally as we do not want it to keep its content across server calls)

    Essence

    You cannot use a type without declaring a variable from it first. That is why your sample did not build. If you try go will complain that Content is not an expression.