gpt4 book ai didi

go - Request 和 ResponseWriter 将被覆盖

转载 作者:IT王子 更新时间:2023-10-29 01:53:07 24 4
gpt4 key购买 nike

我对 go http 包进行了一些实验。

看下面的代码片段,一个非常简单的http服务器:

package main

import (
"fmt"
"github.com/codegangsta/negroni"
"github.com/gorilla/mux"
"net/http"
//"time"
)

type controller struct {
request *http.Request
response http.ResponseWriter
}

func (self *controller) send() {
fmt.Fprintf(self.response, "Request %p and Response %p \n", self.request, self.response)
}

func (self *controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
fmt.Println("Start controller")
self.request = r
self.response = rw

self.send()
}

func main() {

router := mux.NewRouter()
router.Handle("/", &controller{})

n := negroni.Classic()
n.UseHandler(router)

n.Run(":3000")
}

然后我向服务器发出 20 次请求:

package main

import (
"fmt"
"io"
"net/http"
"runtime"
"time"
)

func main() {

buffer := make([]byte, 100)
runtime.GOMAXPROCS(runtime.NumCPU())

for i := 0; i < 20; i++ {
go func(z int) {
//fmt.Println("Request goroutine 1 ", z)
resp, err := http.Get("http://127.0.0.1:3000")
if err != nil {
fmt.Println(err)
}

io.ReadFull(resp.Body, buffer)
fmt.Println(string(buffer))
}(i)
}

time.Sleep(time.Second * 5)

}

我收到了以下回复:

Request 0xc0820201a0 and Response 0xc082007100

Request 0xc082021380 and Response 0xc0820072c0

Request 0xc0820204e0 and Response 0xc082007740

Request 0xc082020dd0 and Response 0xc0820071c0

Request 0xc082020d00 and Response 0xc082007240

Request 0xc082021450 and Response 0xc082007400

Request 0xc082020f70 and Response 0xc082007500

Request 0xc082021110 and Response 0xc082007480

Request 0xc0820212b0 and Response 0xc082007540

Request 0xc082020b60 and Response 0xc0820075c0

Request 0xc082020750 and Response 0xc082007640

Request 0xc082020270 and Response 0xc0820076c0

Request 0xc082020c30 and Response 0xc082007840

Request 0xc082020820 and Response 0xc0820078c0

Request 0xc082020ea0 and Response 0xc082007940

Request 0xc0820211e0 and Response 0xc0820079c0

Request 0xc082021520 and Response 0xc082007a40

Request 0xc0820209c0 and Response 0xc082007ac0

Request 0xc082021040 and Response 0xc082007380

Request 0xc082020a90 and Response 0xc0820077c0

如您所见,一切正常。每个请求和响应都有不同的存储地址。

所以如果我将 http 服务器更改为:

package main

import (
"fmt"
"github.com/codegangsta/negroni"
"github.com/gorilla/mux"
"net/http"
"time"
)

type controller struct {
request *http.Request
response http.ResponseWriter
counter int
}


func (self *controller) get() {
self.counter++
if self.counter == 7 {
time.Sleep(time.Second * 4)
}

fmt.Printf("Request %p and Response %p \n", self.request, self.response)

}

func (self *controller) send() {
fmt.Fprintf(self.response, "Request %p and Response %p \n", self.request, self.response)
}

func (self *controller) ServeHTTP(rw http.ResponseWriter, r *http.Request) {
fmt.Println("Start controller")
self.request = r
self.response = rw

self.get()
self.send()
}

func main() {

router := mux.NewRouter()
router.Handle("/", &controller{})

n := negroni.Classic()
n.UseHandler(router)

n.Run(":3000")
}

正如您在这里看到的,我添加了方法 get,当计数器达到数字 7 时,它将休眠 4 秒。

func (self *controller) get() {
self.counter++
if self.counter == 7 {
time.Sleep(time.Second * 4)
}

fmt.Printf("Request %p and Response %p \n", self.request, self.response)

}

作为输出我有

Request 0xc082021040 and Response 0xc082007100

Request 0xc0820209c0 and Response 0xc082007240

Request 0xc0820211e0 and Response 0xc082007380

Request 0xc082020270 and Response 0xc082007500

Request 0xc082020d00 and Response 0xc082007640

Request 0xc082020f70 and Response 0xc082007740

Request 0xc082020680 and Response 0xc082007840

Request 0xc082020820 and Response 0xc082007940

Request 0xc082020b60 and Response 0xc082007a40

Request 0xc082021380 and Response 0xc0820071c0

Request 0xc082021110 and Response 0xc0820072c0

Request 0xc0820208f0 and Response 0xc082007400

Request 0xc082020a90 and Response 0xc082007540

Request 0xc082020340 and Response 0xc0820076c0

Request 0xc082020750 and Response 0xc0820075c0

Request 0xc082020dd0 and Response 0xc0820077c0

Request 0xc0820212b0 and Response 0xc0820078c0

Request 0xc0820201a0 and Response 0xc0820079c0

Request 0xc082020ea0 and Response 0xc082007ac0

Request 0xc082020ea0 and Response 0xc082007ac0

可以看到最后两行的地址是一样的,也就是说request 7会覆盖request和response的地址,因为response是delay的。

我的问题是,当一个请求必须处理密集的计算时,例如调整图像大小,并且在调整大小期间另一个请求进来,来自图像调整大小过程的请求和响应将像上面那样被覆盖。然后响应将转到最后请求的客户端。在我看来,这是错误的,对吧?

我知道为每个请求创建一个新的 goroutine。

最佳答案

您正在引入数据竞赛:

router.Handle("/", &controller{})

如您所见,controller 类型只有一个实例。

self.request = r
self.response = rw

在这里你正在修改你的结构。但是 ServeHTTP() 方法会被多个 goroutines 调用。

一个选项是像这样创建一个处理程序

router.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
c := &controller{request: r, response: w)
c.send()
...
})

如果您使用 -race 标志运行您的代码,它会警告您这一点。另见 http://blog.golang.org/race-detector

另一件事:不要给你的接收者命名self。这不是惯用语。它使您的代码不可读。什么是 self?给它一个合适的名字。

关于go - Request 和 ResponseWriter 将被覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27153811/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com