我有以下代码:
list = append(list, Item{})
现在,我想知道附加值在列表中采用的索引。如下使用len()-不确定异步代码是否可靠:
appendedIndex := len(list) - 1
由于len()函数执行时,列表中可能附加了另一个值。
我必须使用Mutex还是有其他方法?
答案 0 :(得分:2)
是的,您需要一些同步,例如使用Mutex进行同步。对于您的append
语句,这已经是正确的,因为从不同的go例程同时写入片并不安全。您可以对append
和len
使用相同的保护。 (也许您可以重新设计代码以改为使用通道,而只有一个例程可以访问实际的切片?)
围棋比赛探测器警告此类问题。如果将以下代码放入文件中,请说“ ex_test.go”:
package ex
import (
"sync"
"testing"
)
type Item struct{}
func TestAppend(t *testing.T) {
var list []Item
n := 2
wg := sync.WaitGroup{}
wg.Add(n)
for i := 0; i < n; i++ {
go func() {
defer wg.Done()
list = append(list, Item{})
}()
}
wg.Wait()
}
然后,对go test -race
的呼叫警告“数据竞赛”:
WARNING: DATA RACE
Read at 0x00c0000a4040 by goroutine 8:
_/Users/voss/Desktop.TestAppend.func1()
/Users/voss/Desktop/ex_test.go:19 +0x66
Previous write at 0x00c0000a4040 by goroutine 7:
_/Users/voss/Desktop.TestAppend.func1()
/Users/voss/Desktop/ex_test.go:19 +0xa7
Goroutine 8 (running) created at:
_/Users/voss/Desktop.TestAppend()
/Users/voss/Desktop/ex_test.go:17 +0xfe
testing.tRunner()
/usr/local/go/src/testing/testing.go:827 +0x162
Goroutine 7 (finished) created at:
_/Users/voss/Desktop.TestAppend()
/Users/voss/Desktop/ex_test.go:17 +0xfe
testing.tRunner()
/usr/local/go/src/testing/testing.go:827 +0x162