• Go语言中append()函数的源码实现在哪里?


    今天在学习Go的基础数据结构——slice,期间阅读了slice的内部实现,扩容策略等。然后想到,我们在调用append()函数进行追加元素是究竟发生了什么?于是就想看看append()函数的内部实现,结果源码里并没有找到,搜索一番,还是在StackOverflow上找到了答案。记录如下。

    Q:Where is the implementation of func append in Go?

    A:

    The code you are reading and citing is just dummy code to have consistent documentation. The built-in functions are, well, built into the language and, as such, are included in the code processing step (the compiler).

    Simplified what happens is: lexer(词法分析程序) will detect 'append(...)' as APPEND token, parser will translate APPEND, depending on the circumstances/parameters/environment to code, code is written as assembly and assembled(代码被写成汇编语言,然后进行编译). The middle step - the implementation of append - can be found in the compiler here.

    What happens to an append call is best seen when looking at the assembly of an example program. Consider this:

    b := []byte{'a'}
    b = append(b, 'b')
    println(string(b), cap(b))

    Running it will yield the following output:

    ab 2

    The append call is translated to assembly like this:

    // create new slice object
    MOVQ    BX, "".b+120(SP)       // BX contains data addr., write to b.addr
    MOVQ    BX, CX                 // store addr. in CX
    MOVQ    AX, "".b+128(SP)       // AX contains len(b) == 1, write to b.len
    MOVQ    DI, "".b+136(SP)       // DI contains cap(b) == 1, write to b.cap
    MOVQ    AX, BX                 // BX now contains len(b)
    INCQ    BX                     // BX++
    CMPQ    BX, DI                 // compare new length (2) with cap (1)
    JHI $1, 225                    // jump to grow code if len > cap
    ...
    LEAQ    (CX)(AX*1), BX         // load address of newly allocated slice entry
    MOVB    $98, (BX)              // write 'b' to loaded address
    
    // grow code, call runtime.growslice(t *slicetype, old slice, cap int)
    LEAQ    type.[]uint8(SB), BP
    MOVQ    BP, (SP)               // load parameters onto stack
    MOVQ    CX, 8(SP)
    MOVQ    AX, 16(SP)
    MOVQ    SI, 24(SP)
    MOVQ    BX, 32(SP)
    PCDATA  $0, $0
    CALL    runtime.growslice(SB)  // call
    MOVQ    40(SP), DI
    MOVQ    48(SP), R8
    MOVQ    56(SP), SI
    MOVQ    R8, AX
    INCQ    R8
    MOVQ    DI, CX
    JMP 108                        // jump back, growing done

    As you can see, no CALL statement to a function called append can be seen. This is the full implementation of the append call in the example code. Another call with different parameters will look differently (other registers, different parameters depending on the slice type, etc.).


    参考:

    https://stackoverflow.com/questions/33405327/where-is-the-implementation-of-func-append-in-go

  • 相关阅读:
    摄像头标定
    Call PDF to Vector Converter Command Line from C#, ASP, etc. web program languages
    Camera Calibration and 3D Reconstruction
    C++获取一个文件夹下的所有文件名(转)
    javascript学习之对象应用
    javascript中Array对象总结
    Joomla学习之模块
    关于ci中的表单提交问题
    phpcms之文件目录
    jQuery中的join方法
  • 原文地址:https://www.cnblogs.com/kkbill/p/12534574.html
Copyright © 2020-2023  润新知