Repository: zeromicro/go-zero
Pull request #1593 (2022-02-28 15:08:27)

chore: fix data race


Patch:
diff --git a/core/logx/durationlogger.go b/core/logx/durationlogger.go
index ab26a0a6..7108a939 100644
--- a/core/logx/durationlogger.go
+++ b/core/logx/durationlogger.go
@@ -3,6 +3,7 @@ package logx
 import (
 	"fmt"
 	"io"
+	"sync/atomic"
 	"time"
 
 	"github.com/zeromicro/go-zero/core/timex"
@@ -79,7 +80,7 @@ func (l *durationLogger) WithDuration(duration time.Duration) Logger {
 }
 
 func (l *durationLogger) write(writer io.Writer, level string, val interface{}) {
-	switch encoding {
+	switch atomic.LoadUint32(&encoding) {
 	case plainEncodingType:
 		writePlainAny(writer, level, val, l.Duration)
 	default:
diff --git a/core/logx/logs.go b/core/logx/logs.go
index 81ee4e3e..c0a3315a 100644
--- a/core/logx/logs.go
+++ b/core/logx/logs.go
@@ -33,7 +33,7 @@ const (
 )
 
 const (
-	jsonEncodingType uint32 = iota
+	jsonEncodingType = iota
 	plainEncodingType
 
 	jsonEncoding     = "json"
@@ -75,7 +75,7 @@ var (
 	timeFormat   = "2006-01-02T15:04:05.000Z07:00"
 	writeConsole bool
 	logLevel     uint32
-	encoding     = jsonEncodingType
+	encoding     uint32 = jsonEncodingType
 	// use uint32 for atomic operations
 	disableStat uint32
 	infoLog     io.WriteCloser
@@ -137,9 +137,9 @@ func SetUp(c LogConf) error {
 	}
 	switch c.Encoding {
 	case plainEncoding:
-		setEncoding(plainEncodingType)
+		atomic.StoreUint32(&encoding, plainEncodingType)
 	default:
-		setEncoding(jsonEncodingType)
+		atomic.StoreUint32(&encoding, jsonEncodingType)
 	}
 
 	switch c.Mode {
@@ -424,7 +424,7 @@ func infoTextSync(msg string) {
 }
 
 func outputAny(writer io.Writer, level string, val interface{}) {
-	switch encoding {
+	switch atomic.LoadUint32(&encoding) {
 	case plainEncodingType:
 		writePlainAny(writer, level, val)
 	default:
@@ -438,7 +438,7 @@ func outputAny(writer io.Writer, level string, val interface{}) {
 }
 
 func outputText(writer io.Writer, level, msg string) {
-	switch encoding {
+	switch atomic.LoadUint32(&encoding) {
 	case plainEncodingType:
 		writePlainText(writer, level, msg)
 	default:
@@ -666,7 +666,3 @@ func (lw logWriter) Write(data []byte) (int, error) {
 	lw.logger.Print(string(data))
 	return len(data), nil
 }
-
-func setEncoding(encodingType uint32) {
-	atomic.StoreUint32(&encoding, encodingType)
-}
diff --git a/core/logx/tracelogger.go b/core/logx/tracelogger.go
index e2702d51..647f3dff 100644
--- a/core/logx/tracelogger.go
+++ b/core/logx/tracelogger.go
@@ -4,6 +4,7 @@ import (
 	"context"
 	"fmt"
 	"io"
+	"sync/atomic"
 	"time"
 
 	"github.com/zeromicro/go-zero/core/timex"
@@ -80,7 +81,7 @@ func (l *traceLogger) write(writer io.Writer, level string, val interface{}) {
 	traceID := traceIdFromContext(l.ctx)
 	spanID := spanIdFromContext(l.ctx)
 
-	switch encoding {
+	switch atomic.LoadUint32(&encoding) {
 	case plainEncodingType:
 		writePlainAny(writer, level, val, l.Duration, traceID, spanID)
 	default:
diff --git a/tools/goctl/go.sum b/tools/goctl/go.sum
index 6efd385b..104774e4 100644
--- a/tools/goctl/go.sum
+++ b/tools/goctl/go.sum
@@ -356,8 +356,8 @@ github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da h1:NimzV1aGyq29m5u
 github.com/yuin/gopher-lua v0.0.0-20200816102855-ee81675732da/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA=
 github.com/zeromicro/antlr v0.0.1 h1:CQpIn/dc0pUjgGQ81y98s/NGOm2Hfru2NNio2I9mQgk=
 github.com/zeromicro/antlr v0.0.1/go.mod h1:nfpjEwFR6Q4xGDJMcZnCL9tEfQRgszMwu3rDz2Z+p5M=
-github.com/zeromicro/ddl-parser v1.0.2 h1:bHmxTh8+unNAQoIiCwBdzS49ho6Bb9E0/KrH1HqUwqo=
-github.com/zeromicro/ddl-parser v1.0.2/go.mod h1:ISU/8NuPyEpl9pa17Py9TBPetMjtsiHrb9f5XGiYbo8=
+github.com/zeromicro/ddl-parser v1.0.3 h1:hFecpbt0oPQMhHAbqG1tz78MUepHUnOkFJp1dvRBFyc=
+github.com/zeromicro/ddl-parser v1.0.3/go.mod h1:ISU/8NuPyEpl9pa17Py9TBPetMjtsiHrb9f5XGiYbo8=
 github.com/zeromicro/go-zero v1.3.0 h1:Eyn36yBtR043sm4YKmxR6eS3UA/GtZDktQ+UqIJ3Lm0=
 github.com/zeromicro/go-zero v1.3.0/go.mod h1:Hy4o1VFAt32lXaQMbaBhoFeZjA/rJqJ4PTGNdGsURcc=
 go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=


Test patch:
diff --git a/core/logx/durationlogger_test.go b/core/logx/durationlogger_test.go
index 96eba091..4cebf448 100644
--- a/core/logx/durationlogger_test.go
+++ b/core/logx/durationlogger_test.go
@@ -3,6 +3,7 @@ package logx
 import (
 	"log"
 	"strings"
+	"sync/atomic"
 	"testing"
 	"time"
 
@@ -38,10 +39,10 @@ func TestWithDurationInfo(t *testing.T) {
 }
 
 func TestWithDurationInfoConsole(t *testing.T) {
-	old := encoding
-	encoding = plainEncodingType
+	old := atomic.LoadUint32(&encoding)
+	atomic.StoreUint32(&encoding, plainEncodingType)
 	defer func() {
-		encoding = old
+		atomic.StoreUint32(&encoding, old)
 	}()
 
 	var builder strings.Builder
diff --git a/core/logx/logs_test.go b/core/logx/logs_test.go
index 29d647c2..7ab86c52 100644
--- a/core/logx/logs_test.go
+++ b/core/logx/logs_test.go
@@ -145,10 +145,10 @@ func TestStructedLogInfoConsoleAny(t *testing.T) {
 	doTestStructedLogConsole(t, func(writer io.WriteCloser) {
 		infoLog = writer
 	}, func(v ...interface{}) {
-		old := encoding
-		encoding = plainEncodingType
+		old := atomic.LoadUint32(&encoding)
+		atomic.StoreUint32(&encoding, plainEncodingType)
 		defer func() {
-			encoding = old
+			atomic.StoreUint32(&encoding, old)
 		}()
 
 		Infov(v)
@@ -159,10 +159,10 @@ func TestStructedLogInfoConsoleAnyString(t *testing.T) {
 	doTestStructedLogConsole(t, func(writer io.WriteCloser) {
 		infoLog = writer
 	}, func(v ...interface{}) {
-		old := encoding
-		encoding = plainEncodingType
+		old := atomic.LoadUint32(&encoding)
+		atomic.StoreUint32(&encoding, plainEncodingType)
 		defer func() {
-			encoding = old
+			atomic.StoreUint32(&encoding, old)
 		}()
 
 		Infov(fmt.Sprint(v...))
@@ -173,10 +173,10 @@ func TestStructedLogInfoConsoleAnyError(t *testing.T) {
 	doTestStructedLogConsole(t, func(writer io.WriteCloser) {
 		infoLog = writer
 	}, func(v ...interface{}) {
-		old := encoding
-		encoding = plainEncodingType
+		old := atomic.LoadUint32(&encoding)
+		atomic.StoreUint32(&encoding, plainEncodingType)
 		defer func() {
-			encoding = old
+			atomic.StoreUint32(&encoding, old)
 		}()
 
 		Infov(errors.New(fmt.Sprint(v...)))
@@ -187,10 +187,10 @@ func TestStructedLogInfoConsoleAnyStringer(t *testing.T) {
 	doTestStructedLogConsole(t, func(writer io.WriteCloser) {
 		infoLog = writer
 	}, func(v ...interface{}) {
-		old := encoding
-		encoding = plainEncodingType
+		old := atomic.LoadUint32(&encoding)
+		atomic.StoreUint32(&encoding, plainEncodingType)
 		defer func() {
-			encoding = old
+			atomic.StoreUint32(&encoding, old)
 		}()
 
 		Infov(ValStringer{
@@ -203,10 +203,10 @@ func TestStructedLogInfoConsoleText(t *testing.T) {
 	doTestStructedLogConsole(t, func(writer io.WriteCloser) {
 		infoLog = writer
 	}, func(v ...interface{}) {
-		old := encoding
-		encoding = plainEncodingType
+		old := atomic.LoadUint32(&encoding)
+		atomic.StoreUint32(&encoding, plainEncodingType)
 		defer func() {
-			encoding = old
+			atomic.StoreUint32(&encoding, old)
 		}()
 
 		Info(fmt.Sprint(v...))
diff --git a/core/logx/syslog_test.go b/core/logx/syslog_test.go
index 01b285ee..d2a4fd29 100644
--- a/core/logx/syslog_test.go
+++ b/core/logx/syslog_test.go
@@ -29,9 +29,9 @@ func TestRedirector(t *testing.T) {
 }
 
 func captureOutput(f func()) string {
-	atomic.StoreUint32(&initialized, 1)
 	writer := new(mockWriter)
 	infoLog = writer
+	atomic.StoreUint32(&initialized, 1)
 
 	prevLevel := atomic.LoadUint32(&logLevel)
 	SetLevel(InfoLevel)
@@ -44,5 +44,9 @@ func captureOutput(f func()) string {
 func getContent(jsonStr string) string {
 	var entry logEntry
 	json.Unmarshal([]byte(jsonStr), &entry)
-	return entry.Content.(string)
+	val, ok := entry.Content.(string)
+	if ok {
+		return val
+	}
+	return ""
 }
diff --git a/core/logx/tracelogger_test.go b/core/logx/tracelogger_test.go
index 1427e736..3fa4d2ed 100644
--- a/core/logx/tracelogger_test.go
+++ b/core/logx/tracelogger_test.go
@@ -83,10 +83,10 @@ func TestTraceInfo(t *testing.T) {
 }
 
 func TestTraceInfoConsole(t *testing.T) {
-	old := encoding
-	setEncoding(jsonEncodingType)
+	old := atomic.LoadUint32(&encoding)
+	atomic.StoreUint32(&encoding, jsonEncodingType)
 	defer func() {
-		setEncoding(old)
+		atomic.StoreUint32(&encoding, old)
 	}()
 
 	var buf mockWriter