i found that this package will raise data race condition if we call WithContext function every time before we call the command function, e.g, Set or Get function.
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"sync"
goredis "github.com/go-redis/redis"
"gopkg.in/DataDog/dd-trace-go.v1/contrib/go-redis/redis"
)
func main() {
closeApp := make(chan struct{})
redisOpt := &goredis.Options{
DB: 0,
Addr: "localhost:6379",
Password: "",
}
redisClient := redis.NewClient(redisOpt)
go func() {
sigint := make(chan os.Signal, 1)
signal.Notify(sigint, os.Interrupt)
<-sigint
if err := redisClient.Close(); err != nil {
log.Fatal(fmt.Sprintf("error when closing redis client. err: %+v\n", err))
}
closeApp <- struct{}{}
}()
var wg sync.WaitGroup
wg.Add(2000)
for i := 1; i <= 2000; i++ {
go writeData(&wg, redisClient, i)
}
wg.Wait()
for i := 1; i <= 2000; i++ {
go fetchData(redisClient, i)
}
<-closeApp
close(closeApp)
}
func writeData(wg *sync.WaitGroup, redisClient *redis.Client, iterationNum int) {
defer wg.Done()
key := fmt.Sprintf("test_key:%d", iterationNum)
val, err := redisClient.WithContext(context.Background()).Set(key, iterationNum, 0).Result()
if err != nil {
log.Printf("[write] error while writing data. iteration: %d. err: %+v\n", iterationNum, err)
return
}
log.Printf("[write] iteration: %d. \nkey written: %s\n value written: %d\n value returned: %s\n",
iterationNum, key, iterationNum, val)
}
func fetchData(redisClient *redis.Client, iterationNum int) {
key := fmt.Sprintf("test_key:%d", iterationNum)
val, err := redisClient.WithContext(context.Background()).Get(key).Result()
if err != nil {
log.Printf("[read] error while fetching data. iteration: %d. err: %+v\n", iterationNum, err)
return
}
log.Printf("[read] iteration: %d\n key read: %s\n value read: %s", iterationNum, key, val)
}
i found that this package will raise data race condition if we call WithContext function every time before we call the command function, e.g, Set or Get function.