len()运行多少次?

时间:2013-02-02 13:38:42

标签: go

len(p)运行多少次?只保存一个,结果会保存,还是每次迭代运行一次?

func main() {
    p := []int{2, 3, 5, 7, 11, 13}
    for i:=0;i<len(p);i++ {}
}

4 个答案:

答案 0 :(得分:10)

切片上的

len()由编译器优化,就像访问局部变量一样。这不是函数调用。

您可以通过以下方式验证:

$ cat x.go
package main
import "fmt"
func main() {
    a := []int{1,2, 3}
    fmt.Println(len(a))
}

然后查看编译器输出:

$ go tool 6g -S x.go

--- prog list "main" ---
0000 (x.go:3) TEXT    main+0(SB),$128-0
0001 (x.go:4) MOVQ    $0,autotmp_0002+-80(SP)
0002 (x.go:4) MOVQ    $0,autotmp_0002+-72(SP)
0003 (x.go:4) MOVQ    $0,autotmp_0002+-64(SP)
0004 (x.go:4) LEAQ    autotmp_0002+-80(SP),BX
0005 (x.go:4) MOVQ    BX,autotmp_0001+-56(SP)
0006 (x.go:4) MOVQ    autotmp_0001+-56(SP),BX
0007 (x.go:4) MOVQ    statictmp_0000+0(SB),BP
0008 (x.go:4) MOVQ    BP,(BX)
0009 (x.go:4) MOVQ    statictmp_0000+8(SB),BP
0010 (x.go:4) MOVQ    BP,8(BX)
0011 (x.go:4) MOVQ    statictmp_0000+16(SB),BP
0012 (x.go:4) MOVQ    BP,16(BX)
0013 (x.go:4) MOVQ    autotmp_0001+-56(SP),BX
0014 (x.go:4) MOVQ    $3,CX
0015 (x.go:5) LEAQ    autotmp_0005+-16(SP),DI
0016 (x.go:5) MOVQ    $0,AX
0017 (x.go:5) STOSQ   ,
0018 (x.go:5) STOSQ   ,
0019 (x.go:5) LEAQ    autotmp_0005+-16(SP),BX
0020 (x.go:5) MOVQ    BX,autotmp_0004+-48(SP)
0021 (x.go:5) MOVQ    autotmp_0004+-48(SP),BX
0022 (x.go:5) MOVQ    $1,SI
0023 (x.go:5) MOVQ    $1,DX
0024 (x.go:5) MOVQ    BX,autotmp_0003+-40(SP)
0025 (x.go:5) MOVQ    autotmp_0003+-40(SP),BX
0026 (x.go:5) MOVQ    $type.int+0(SB),AX
0027 (x.go:5) MOVQ    AX,(BX)
0028 (x.go:5) MOVQ    CX,8(BX)
0029 (x.go:5) MOVQ    autotmp_0003+-40(SP),BX
0030 (x.go:5) MOVQ    BX,(SP)
0031 (x.go:5) MOVQ    SI,8(SP)
0032 (x.go:5) MOVQ    DX,16(SP)
0033 (x.go:5) CALL    ,fmt.Println+0(SB)
0034 (x.go:6) RET     ,

请注意fmt.Println的CALL,但不要拨打len

答案 1 :(得分:9)

尝试实验! http://play.golang.org/p/Eksb6bQovC

或阅读文档:http://golang.org/ref/spec#For_statements(TL; DR:“在每次迭代之前评估条件。”

在您的示例中,len是条件的一部分,因此在每次迭代之前对其进行求值。将条件评估为真的六次迭代,然后再评估一次,其中评估为false并且for循环退出。所以,总共七次。

答案 2 :(得分:2)

第二个实验:

func Test_X(t * testing.T) {
    list := []int{1, 2, 3}
    fmt.Printf("# b: len(list) %d\n", len(list))
    for i := 0; i < len(list); i++ {
        fmt.Printf("# %d: len(list) %d, list[%d] == %d\n", i, len(list), i, list[i])
        if i == 2 {
            list = append(list, 4)
        }
    }
    fmt.Printf("# a: len(list) %d\n", len(list))
}

输出:

=== RUN Test_X
# b: len(list) 3
# 0: len(list) 3, list[0] == 1
# 1: len(list) 3, list[1] == 2
# 2: len(list) 3, list[2] == 3
# 3: len(list) 4, list[3] == 4
# a: len(list) 4
--- PASS: Test_X (0.05 seconds)

它给出了不优化然后调用len()的原因。

答案 3 :(得分:-4)

从算法的角度来看,为循环的每个步骤评估条件。在这种情况下,似乎是对len(p)的评估的六倍。