将闭包声明为循环(在性能的上下文中)

时间:2015-07-24 21:32:51

标签: go closures

以下三种实现之间是否存在差异(在性能方面)?:

mustGetSpeed := func() string {
    ...
    return speed
}

for _, item := range items {
    speed, err := strconv.Atoi(mustGetSpeed())
    ...
}
for _, item := range items {
    mustGetSpeed := func() string {
        ...
        return speed
    }
    speed, err := strconv.Atoi(mustGetSpeed())
    ...
}
for _, item := range items {
    speed, err := strconv.Atoi(func() string {
        ...
        return speed
    }())
    ...
}

这是一个错误(在性能的上下文中)声明闭包到循环中吗?

1 个答案:

答案 0 :(得分:1)

您正在推测性能问题。不要这样做。得到一些事实。运行一些基准测试。例如,

package main

import (
    "strconv"
    "testing"
)

const sound = "1236" // speed of sound 1,236 kilometres per hour

var items = make([]int, 1024)

func BenchmarkClosure1(b *testing.B) {
    for i := 0; i < b.N; i++ {
        mustGetSpeed := func() string {
            speed := sound
            // ...
            return speed
        }
        for _, item := range items {
            speed, err := strconv.Atoi(mustGetSpeed())
            // ...
            _, _, _ = item, speed, err
        }
    }
}

func BenchmarkClosure2(b *testing.B) {
    for i := 0; i < b.N; i++ {
        for _, item := range items {
            mustGetSpeed := func() string {
                speed := sound
                // ...
                return speed
            }
            speed, err := strconv.Atoi(mustGetSpeed())
            // ...
            _, _, _ = item, speed, err
        }
    }
}

func BenchmarkClosure3(b *testing.B) {
    for i := 0; i < b.N; i++ {
        for _, item := range items {
            speed, err := strconv.Atoi(func() string {
                speed := sound
                // ...
                return speed
            }())
            // ...
            _, _, _ = item, speed, err
        }
    }
}

输出:

BenchmarkClosure1      10000        156031 ns/op
BenchmarkClosure2      10000        156955 ns/op
BenchmarkClosure3      10000        152546 ns/op