在Golang中使用net/http存储每个请求的结构值。

huangapple go评论145阅读模式
英文:

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

问题

我是新手学习 Golang,我正在测试 net/http 包来运行一些路径,但是我遇到了一些我不理解的问题。

以下是我的代码:

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)
}

所以,当我访问 http://localhost:8080/ 时,我得到了空的内容 index content {{false } map[]}

而当我访问 http://localhost:8080/test 时,我得到了正确的内容,test content {{false } map[data1:data 1 content data2:data 2 content]}

但是当我回到首页 http://localhost:8080/ 时,那里已经有内容了,index content {{false } map[data1:data 1 content data2:data 2 content]}

所以问题是,为什么当我回到首页时,我没有得到空的结构体内容?我以为结构体会在每个请求时都处于初始状态?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?

答案1

得分: 1

你可能正在经历的是这段代码或类似的代码的结果(你的代码无法编译):

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)
}

解决方案

你创建了一个全局变量 Content,它在对 web 服务器的多次调用之间保持状态。你可能想要的是这样的:

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)
}

所做的更改

  • Content 声明为类型,就像你在示例中已经做的那样(这样它不再是全局变量,而是定义了一个我们可以重用的类型)
  • 在需要的每个调用中声明 Content(不要全局声明,因为我们不希望它在服务器调用之间保持内容)

要点

在使用类型之前,你必须先声明一个变量。这就是为什么你的示例无法构建的原因。如果你尝试这样做,Go 将会抱怨 Content 不是一个表达式。

英文:

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.

huangapple
  • 本文由 发表于 2017年8月11日 03:18:15
  • 转载请务必保留本文链接:https://go.coder-hub.com/45621902.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定