İçeriğe geç

Ara katmanda goroutine'ler

Bir ara katman veya işleyici içinde yeni Goroutine’ler başlatırken, içinde orijinal context’i KULLANMAMALISINIZ, salt okunur bir kopya kullanmanız gerekir.

c.Copy() neden gereklidir

Gin, performans için istekler arasında gin.Context nesnelerini yeniden kullanmak üzere bir sync.Pool kullanır. Bir işleyici döndüğünde, gin.Context havuza geri döner ve tamamen farklı bir isteğe atanabilir. Bir goroutine bu noktada hâlâ orijinal context’e bir referans tutuyorsa, artık başka bir isteğe ait olan alanları okuyacak veya yazacaktır. Bu, yarış koşullarına, veri bozulmasına veya panic’lere yol açar.

c.Copy() çağrısı, işleyici döndükten sonra kullanılması güvenli olan context’in bir anlık görüntüsünü oluşturur. Kopya, istek, URL, anahtarlar ve diğer salt okunur verileri içerir, ancak havuz yaşam döngüsünden ayrılmıştır.

package main
import (
"log"
"time"
"github.com/gin-gonic/gin"
)
func main() {
router := gin.Default()
router.GET("/long_async", func(c *gin.Context) {
// create copy to be used inside the goroutine
cCp := c.Copy()
go func() {
// simulate a long task with time.Sleep(). 5 seconds
time.Sleep(5 * time.Second)
// note that you are using the copied context "cCp", IMPORTANT
log.Println("Done! in path " + cCp.Request.URL.Path)
}()
})
router.GET("/long_sync", func(c *gin.Context) {
// simulate a long task with time.Sleep(). 5 seconds
time.Sleep(5 * time.Second)
// since we are NOT using a goroutine, we do not have to copy the context
log.Println("Done! in path " + c.Request.URL.Path)
})
// Listen and serve on 0.0.0.0:8080
router.Run(":8080")
}