go - 高并发下Go `net/http`的一些困惑

标签 go logging go-gin

高并发下的一些困惑。

我使用 wrk测试 Gin ,有一些不确定性。 Gin 似乎并发不安全。

  package main

  import (
    "fmt"
    "sync/atomic"

    "github.com/gin-gonic/gin"
  )

  var count int64 = 0

  func Test(c *gin.Context) {
    atomic.AddInt64(&count, 1)
    fmt.Println(count)
    c.String(200, "success")
  }

  func main() {
    gin.SetMode(gin.DebugMode)
    router := gin.New()
    router.GET("test", Test)
    router.Run(":8080")
  }

测试shell代码

  wrk -t50 -c50 -d 1s http://localhost:8080/test

gin输出重复数据

duplicate data

========更新========

即使打印代码是这样的。

  countCopy := count
  go func() {
    fmt.Println(countCopy)
  }()

我也用ab测试一下,同样的问题。

========更新========

和net/http一样,还是有重复数据。

  package main

  import (
    "fmt"
    "net/http"
    "sync/atomic"
  )

  var count int64 = 0

  func Test(w http.ResponseWriter, req *http.Request) {
    atomic.AddInt64(&count, 1)
    fmt.Println(count)
    w.Write([]byte("success"))
  }

  func main() {
    http.HandleFunc("/test", Test)
    http.ListenAndServe(":8080", nil)

  }

data

我尝试使用日志包,它对并发 goroutines 是安全的。一样。

log.Println(countCopy)

最佳答案

您必须使用 atomic.AddInt64(&count, 1) 的返回值,因为 count 可以在您有机会打印之前更改:

func Test(c *gin.Context) {
    current := atomic.AddInt64(&count, 1)
    fmt.Println(current)
    c.String(200, "success")
}

关于go - 高并发下Go `net/http`的一些困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50267112/

相关文章:

angular - 为 Nativescript 移动应用程序在本地开发 Golang 后端

C# 从 MySQL 读取重复同一行

Golang Gin "c.Param undefined (type *gin.Context has no field or method Param)"

go.mod 使用没有标签的模块

go - 将任意数量的字节读入缓冲区 Golang

Golang 在尝试使方法并发时没有任何返回

c++ - 观察 QStringList 的新项目

去 Gin : Validating base64

go - 如何复制公共(public)变量使用去?

java - Log4j、日志记录、Eclipse