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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM