计算调用函数的次数

时间:2017-11-21 20:39:34

标签: function go

我怎样才能在go中优雅地做到这一点?

在python中我可以使用这样的属性:

def function():
    function.counter += 1
function.counter = 0

go是否有同样的机会?

3 个答案:

答案 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?

The Go Memory Model

这是一个有趣的解决方案(出于同样的原因@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

相关问题