我怎样才能在go
中优雅地做到这一点?
在python中我可以使用这样的属性:
def function():
function.counter += 1
function.counter = 0
go
是否有同样的机会?
答案 0 :(得分:4)
var doThingCounter = 0
func DoThing() {
// Do the thing...
doThingCounter++
}
答案 1 :(得分:4)
例如,
count.go
:
package main
import (
"fmt"
"sync"
"time"
)
type Count struct {
mx *sync.Mutex
count int64
}
func NewCount() *Count {
return &Count{mx: new(sync.Mutex), count: 0}
}
func (c *Count) Incr() {
c.mx.Lock()
c.count++
c.mx.Unlock()
}
func (c *Count) Count() int64 {
c.mx.Lock()
count := c.count
c.mx.Unlock()
return count
}
var fncCount = NewCount()
func fnc() {
fncCount.Incr()
}
func main() {
for i := 0; i < 42; i++ {
go fnc()
}
time.Sleep(time.Second)
fmt.Println(fncCount.Count())
}
输出:
$ go run count.go
42
另外,运行竞赛检测器,
$ go run -race count.go
42
请参阅:
Introducing the Go Race Detector
Benign data races: what could possibly go wrong?
这是一个有趣的解决方案(出于同样的原因@maerics answer很生气),
package main
import (
"fmt"
"time"
)
var fncCount = 0
func fnc() {
fncCount++
}
func main() {
for i := 0; i < 42; i++ {
go fnc()
}
time.Sleep(time.Second)
fmt.Println(fncCount)
}
输出:
$ go run racer.go
39
并且,使用竞赛检测器,
输出:
$ go run -race racer.go
==================
WARNING: DATA RACE
Read at 0x0000005b5380 by goroutine 7:
main.fnc()
/home/peter/gopath/src/so/racer.go:11 +0x3a
Previous write at 0x0000005b5380 by goroutine 6:
main.fnc()
/home/peter/gopath/src/so/racer.go:11 +0x56
Goroutine 7 (running) created at:
main.main()
/home/peter/gopath/src/so/racer.go:16 +0x4f
Goroutine 6 (finished) created at:
main.main()
/home/peter/gopath/src/so/racer.go:16 +0x4f
==================
42
Found 1 data race(s)
exit status 66
$
答案 2 :(得分:4)
让我引用原子包文档:
Package atomic提供了有用的低级原子内存原语 实现同步算法。 https://golang.org/pkg/sync/atomic/
相同的代码,但也更简单,更安全。
package main
import (
"fmt"
"sync/atomic"
"time"
)
var fncCount uint64
func fnc() {
atomic.AddUint64(&fncCount, 1)
}
func main() {
for i := 0; i < 42; i++ {
go fnc()
}
// this is bad, because it won't wait for the goroutines finish
time.Sleep(time.Second)
fncCountFinal := atomic.LoadUint64(&fncCount)
fmt.Println(fncCountFinal)
}
$ go run -race main.go
42