Go中func append的实现在哪里? [英] Where is the implementation of func append in Go?

查看:54
本文介绍了Go中func append的实现在哪里?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对go非常感兴趣,并尝试阅读go函数的实现.我发现其中一些功能在那里没有实现.

I'm very interested in go, and trying to read go function's implementations. I found some of these function doesn't have implementations there.

例如追加或调用:

// The append built-in function appends elements to the end of a slice. If
// it has sufficient capacity, the destination is resliced to accommodate the
// new elements. If it does not, a new underlying array will be allocated.
// Append returns the updated slice. It is therefore necessary to store the
// result of append, often in the variable holding the slice itself:
//  slice = append(slice, elem1, elem2)
//  slice = append(slice, anotherSlice...)
// As a special case, it is legal to append a string to a byte slice, like this:
//  slice = append([]byte("hello "), "world"...)
func append(slice []Type, elems ...Type) []Type

// call calls fn with a copy of the n argument bytes pointed at by arg.
// After fn returns, reflectcall copies n-retoffset result bytes
// back into arg+retoffset before returning. If copying result bytes back,
// the caller must pass the argument frame type as argtype, so that
// call can execute appropriate write barriers during the copy.
func call(argtype *rtype, fn, arg unsafe.Pointer, n uint32, retoffset uint32)

似乎没有调用C代码,因为使用cgo需要一些特殊的注释.这些功能的实现在哪里?

It seems not calling a C code, because using cgo needs some special comments. Where is these function's implementations?

推荐答案

您正在阅读和引用的代码只是具有一致文档的伪代码.内置函数很好地内置在该语言中,因此包含在代码处理步骤(编译器)中.

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).

简化的操作是:lexer将检测到 append(...)'作为 APPEND 令牌,解析器将翻译 APPEND ,具体取决于根据代码的环境/参数/环境,将代码编写为汇编和汇编.中间步骤- append 的实现-可以在编译器

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.

在查看示例程序的程序集时,最好能看到 append 调用发生了什么.考虑一下:

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

append 调用转换为如下形式的程序集:

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

如您所见,看不到名为 append 的函数的 CALL 语句.这是示例代码中 append 调用的完整实现.另一个具有不同参数 的调用的外观会有所不同(其他寄存器,取决于切片类型的不同参数,等等).

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.).

这篇关于Go中func append的实现在哪里?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆