是個非常難找的錯誤類型之一
Data races are among the most common and hardest to debug types of bugs in concurrent systems. A data race occurs when two goroutines access the same variable concurrently and at least one of the accesses is a write. - golang 官網
講到 Data Race 大家可以來看 weiweiwesley的這篇 - Day10 Race Condition
golang code
package main
import "fmt"
func main() {
c := make(chan bool)
m := make(map[string]string)
go func() {
m["1"] = "a" // First conflicting access.
c <- true
}()
m["2"] = "b" // Second conflicting access.
<-c
for k, v := range m {
fmt.Println(k, v)
}
fmt.Println("Hello, ithome")
}
執行
go run -race main.go
馬上就能看到 data race的警告
==================
WARNING: DATA RACE
Write at 0x00c000092180 by goroutine 7:
runtime.mapassign_faststr()
/usr/local/go/src/runtime/map_faststr.go:202 +0x0
main.main.func1()
/ithome/main.go:9 +0x5d
Previous write at 0x00c000092180 by main goroutine:
runtime.mapassign_faststr()
/usr/local/go/src/runtime/map_faststr.go:202 +0x0
main.main()
/ithome/main.go:12 +0xc6
Goroutine 7 (running) created at:
main.main()
/ithome/main.go:8 +0x97
==================
2 b
1 a
Found 1 data race(s)
還有另一種情況是
造成 data race的code 可能需要某些條件才會被執行到!
package main
import "fmt"
func main() {
_, err := fmt.Println("Hello, ithome")
if err != nil {
gorace()
}
}
func gorace() {
c := make(chan bool)
m := make(map[string]string)
go func() {
m["1"] = "a" // First conflicting access.
c <- true
}()
m["2"] = "b" // Second conflicting access.
<-c
for k, v := range m {
fmt.Println(k, v)
}
}
dockerfile
FROM golang:1.14
WORKDIR /ithome
COPY . /ithome
RUN cd /ithome && go build -race
CMD ["./ithome"]
==================
WARNING: DATA RACE
Write at 0x00c000066250 by goroutine 7:
runtime.mapassign_faststr()
/usr/local/go/src/runtime/map_faststr.go:202 +0x0
main.main.func1()
/ithome/main.go:9 +0x5d
Previous write at 0x00c000066250 by main goroutine:
runtime.mapassign_faststr()
/usr/local/go/src/runtime/map_faststr.go:202 +0x0
main.main()
/ithome/main.go:12 +0xc9
Goroutine 7 (running) created at:
main.main()
/ithome/main.go:8 +0x9a
==================
2 b
1 a
Hello, ithome
Found 1 data race(s)
example for drone:
Drone Ppipeline
kind: pipeline
type: docker
name: default
steps:
- name: golangci-lint
image: golangci/golangci-lint:v1.31.0-alpine
commands:
- golangci-lint run
- name: gcp_push_image
image: docker:dind
volumes:
- name: docker
path: /var/run/docker.sock
commands:
- docker build --no-cache --pull --force-rm -t ithome/${DRONE_REPO_NAME}:latest -f go.dockerfile .
volumes:
- name: docker
host:
path: /var/run/docker.sock
Status: Downloaded newer image for golang:1.14-alpine
---> 0223ac8ea40d
Step 2/5 : WORKDIR /ithome
---> Running in 2af0d6741a36
Removing intermediate container 2af0d6741a36
---> 0c4a85e3a1d2
Step 3/5 : COPY . /ithome
---> 793671813d82
Step 4/5 : RUN cd /ithome && go build -race
---> Running in 1a5c3093f6aa
# runtime/cgo
exec: "gcc": executable file not found in $PATH