在Golang中是否可能内联包含循环的函数?

15

例如,我在Golang中有以下测试:

// inline-tests.go
package inlinetests

func plus(a, b int) int {
    return a + b
}

func plus_plus(a, b, c int) int {
    return plus(plus(a, b), plus(b, c))
}

func plus_iter(l ...int) (res int) {
    for _, v := range l {
        res += v
    }
    return
}
如果我尝试构建它,我会收到以下消息:
go build -gcflags=-m inline-tests.go
# command-line-arguments
./inline-tests.go:4: can inline plus
./inline-tests.go:8: can inline plus_plus
./inline-tests.go:9: inlining call to plus
./inline-tests.go:9: inlining call to plus
./inline-tests.go:9: inlining call to plus
./inline-tests.go:12: plus_iter l does not escape

有没有办法让编译器内联 plus_iter? 如果 ,是否有办法内联映射迭代?


4
内联的规则可以在这里找到:激活代码内联 - icza
没有手动控制哪些内容需要内联,哪些不需要,所以:不行。 - Volker
@icza 那里没有关于循环的内容,是吗? - Grigorii Sokolik
我刚刚进行了一个快速测试,用等效的标签和goto语句替换for循环可以实现内联,这让我感到惊讶,因为我认为循环不能被内联有一些技术上的原因。 - thomasrutter
2个回答

25

Go Wiki

编译器优化

函数内联

只有短小简单的函数才会被内联。要进行内联,函数必须包含不到40个表达式,并且不包含复杂的东西,例如函数调用、循环、标签、闭包、panic's、recover's、select's、switch'es等等。

目前,带有循环的函数不会被内联。


9
截至 Go 1.16 版本: https://golang.org/doc/go1.16#compiler 编译器现在可以内联带有非标记 for 循环、方法值和类型开关的函数。内联器还可以检测更多间接调用,以便进行内联。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接