gpt4 book ai didi

go - Go中func append的实现在哪里?

转载 作者:IT王子 更新时间:2023-10-29 00:34:16 26 4
gpt4 key购买 nike

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

如追加或调用:

// 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需要一些特殊的注释。这些功能的实现在哪里?

最佳答案

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

简化后发生的事情是:词法分析器将检测 'append(...)' 作为 APPEND 标记,解析器将翻译 APPEND,具体取决于根据情况/参数/环境来编码,代码被编写为汇编和组装。中间步骤 - append 的实现 - 可以在编译器中找到 here .

append 调用发生了什么最好看示例程序的汇编。考虑一下:

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

运行它会产生以下输出:

ab 2

append 调用被翻译成这样的程序集:

// 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 调用的完整实现。具有不同参数的另一个调用看起来不同(其他寄存器、不同参数取决于 slice 类型等)。

关于go - Go中func append的实现在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33405327/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com