英文:
sync.Mutex or http.HandleFunc not working
问题
我正在使用《The Go Programming Language》这本教材,其中介绍了如何使用Go创建一个Web服务器。
按照书中给出的代码,我创建了一个Web服务器:
package main
import (
"fmt"
"log"
"net/http"
"sync"
)
var mu sync.Mutex
var count int
func main() {
http.HandleFunc("/", handler)
http.HandleFunc("/count", counter)
log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
count++
mu.Unlock()
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}
func counter(w http.ResponseWriter, r *http.Request) {
mu.Lock()
fmt.Fprintf(w, "Count %d\n", count)
mu.Unlock()
}
然后,我想通过使用goroutine来测试自己的知识,所以我编写了一个程序,将调用服务器的端点"/rest" 1000次。
然后我调用了端点"/count",它应该返回之前端点被调用的次数。
send.go
package main
import (
"fmt"
"net/http"
"os"
"strconv"
"io/ioutil"
)
func main() {
times, _ := strconv.Atoi(os.Args[1])
for i := 0; i < times; i++ {
go call()
}
response, err := http.Get("http://localhost:8080/count")
if err != nil {
fmt.Println("ERROR ", err)
}
text, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(text))
response.Body.Close()
}
func call() {
_, _= http.Get("http://localhost:8080/rest")
}
问题是:"/count"端点返回的数字小于1000。请告诉我我做错了什么,或者我是否对sync.Mutex或http.HandleFunc()的工作原理有误解。
英文:
I am using the textbook: "The Go Programming Language" and in it they show how to make a webserver using Go.
Following the code they give, I made a webserver:
package main
import (
"fmt"
"log"
"net/http"
"sync"
)
var mu sync.Mutex
var count int
func main() {
http.HandleFunc("/", handler)
http.HandleFunc("/count", counter)
log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
func handler(w http.ResponseWriter, r *http.Request) {
mu.Lock()
count++
mu.Unlock()
fmt.Fprintf(w, "URL.Path = %q\n", r.URL.Path)
}
func counter(w http.ResponseWriter, r *http.Request) {
mu.Lock()
fmt.Fprintf(w, "Count %d\n", count)
mu.Unlock()
}
Afterwards I wanted to test my knowledge with goroutines so I made a program that will call the server endpoint: "/rest" 1000 times.
Then I call the endpoint: "/count" which is suppose to return the amount of times the previous endpoint was called.
send.go
package main
import (
"fmt"
"net/http"
"os"
"strconv"
"io/ioutil"
)
func main() {
times, _ := strconv.Atoi(os.Args[1])
for i := 0; i < times; i++ {
go call()
}
response, err := http.Get("http://localhost:8080/count")
if err != nil {
fmt.Println("ERROR ", err)
}
text, _ := ioutil.ReadAll(response.Body)
fmt.Println(string(text))
response.Body.Close()
}
func call() {
_, _= http.Get("http://localhost:8080/rest")
}
The problem is this: the /count endpoint returns a number less than 1000. Please tell me what I am doing wrong, or if there is I'm misunderstanding about how sync.Mutex or http.HandleFunc() works.
答案1
得分: 2
互斥锁只能确保没有两个goroutine同时读写count
,然而它不能控制这些goroutine执行的顺序。
这意味着你的代码中没有任何东西能确保在执行http.Get(".../count")
之前所有的go call()
都已经完成。
如果你想在所有的go call()
完成之后才执行http.Get(".../count")
,你可以使用sync.WaitGroup
来实现。
英文:
The mutex only ensures that no two goroutines will write/read count
at the same time, however it does not control the order in which those goroutines are executed.
That means that there is nothing in your code that ensures that all of the go call()
are finished before http.Get(".../count")
is executed.
If you want to execute http.Get(".../count")
only after all of the go call()
are finished, then you can do that by using a sync.WaitGroup
.
答案2
得分: 0
sync.Mutex
和http.HandleFunc
的工作正常,但每个处理程序都在自己的go协程中运行。无论它们被发布到服务器的顺序如何,都不能保证在调用count
之前运行对handler
的任何调用。
在您的测试程序中,您可以在call()
之前删除go
关键字,这将确保所有请求按顺序运行,因为Get()
等待服务器返回。或者,您可以使用评论中建议的WaitGroup
,它允许请求并行处理,但在发送计数请求之前等待它们全部完成。
英文:
sync.Mutex
and http.HandleFunc
are working as they should, but every handler is run in it's own go-routine. There is no guarantee that any call to handler
is run before the call to count
irrespective of the order they are posted to the server.
In your test program you can remove the go
keyword before call()
which will ensure that all the requests are run in series, since Get()
waits for a return from the server. Or you could use the WaitGroup
as suggested in the comments which would allow the requests to be processed in parallel but wait for them all to finish before sending the count request.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论