统计动态URL调用次数

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

Go count dynamic url calls

问题

我正在尝试计算每个新的动态URL的数量:

var count int

// *错误* 非声明语句在函数体外
func increment() error {
	count = count + 1
	return nil
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]int)
	if r.Method != "POST" {
		http.Error(w, "不支持的方法。", http.StatusNotFound)
		return
	}
	increment()
	b, err := ioutil.ReadAll(r.Body)

	if err != nil {
		panic(err)
	}

	urlPath := r.RequestURI
	value, ok := m[urlPath]
	if ok {
		m[urlPath] = count + 1
		fmt.Println("value: ", value)
	} else {
		m[urlPath] = count
		fmt.Println(m)
		fmt.Println("未找到键")
	}
	fmt.Println(m)

	fmt.Fprintf(w, "Hello!", count)
	fmt.Printf("%s", b)


}

func main() {
	http.HandleFunc("/report/", helloHandler) // 更新此行代码

	fmt.Printf("在端口8080上启动服务器\n")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}

结果应该是一个包含所有URL作为键和次数作为值的映射,例如:
{"abc": 2, "foo": 1, "ho": 5}
但是当我运行我的代码时,每次键都会被更新一次。

英文:

I am trying to count each new dynamic URL

var count int

// *Error* non-declaration statement outside function body
func increment() error {
	count = count + 1
	return nil
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	m := make(map[string]int)
	if r.Method != "POST" {
		http.Error(w, "Method is not supported.", http.StatusNotFound)
		return
	}
	increment()
	b, err := ioutil.ReadAll(r.Body)

	if err != nil {
		panic(err)
	}

	urlPath := r.RequestURI
	value, ok := m[urlPath]
	if ok {
		m[urlPath] = count + 1
		fmt.Println("value: ", value)
	} else {
		m[urlPath] = count
		fmt.Println(m)
		fmt.Println("key not found")
	}
	fmt.Println(m)

	fmt.Fprintf(w, "Hello!", count)
	fmt.Printf("%s", b)


}

func main() {
	http.HandleFunc("/report/", helloHandler) // Update this line of code

	fmt.Printf("Starting server at port 8080\n")
	if err := http.ListenAndServe(":8080", nil); err != nil {
		log.Fatal(err)
	}
}

the result should be map with all URLs as a key and number of times as value such:
{"abc" : 2
"foo" : 1
"ho": 5}
but when i run my code evry time the key updated again an agin

答案1

得分: 2

有多个问题:

  • 每次执行处理程序函数时都会创建一个新的映射。

  • 由于HTTP处理程序在并发运行的单独goroutine上执行,全局变量counter存在数据竞争。

我不确定我是否正确解析了你的意思,但是你应该:

  • 有一个全局映射。
  • 每次访问该映射时都要使用互斥锁进行保护。
  • 递增映射中的计数器值。

类似这样的代码:

var (
  hitsMu sync.Mutex
  hits = make(map[string]*int)
)

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

  hitsMu.Lock()
  defer hitsMu.Unlock()

  counterPtr := hits[urlPath]
  if counterPtr == nil {
    counterPtr = new(int)
    hits[urlPath] = counterPtr
  }
  *counterPtr += 1

  // ...
}
英文:

There are multiple problems:

  • You create a new map on each execution of your handler function.

  • As HTTP handlers execute on separate goroutines which are running concurrently, you have a data race on the global counter variable.

I'm not really sure I have correctly parsed what you're after, but supposedly you should:

  • Have a global map.
  • Have each access to that map protected by a mutex.
  • Increment counters which are values in the map.

Something like this:

var (
  hitsMu sync.Mutex
  hits = make(map[string]*int)
)

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

  hitsMu.Lock()
  defer hitsMu.Unlock()

  counterPtr := hits[urlPath]
  if counterPtr == nil {
    counterPtr = new(int)
    hits[urlPath] = counterPtr
  }
  *counterPtr += 1

  // ...
}

huangapple
  • 本文由 发表于 2022年1月21日 22:57:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/70803286.html
匿名

发表评论

匿名网友

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

确定