我对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需要一些特殊的注释。这些功能的实现在哪里?
您正在阅读和引用的代码只是具有一致文档的伪代码。内置函数很好地内置在语言中,因此包含在代码处理步骤(编译器)中。
简化的过程是:lexer将检测' append(...)
'为APPEND
令牌,解析器将APPEND
根据情况/参数/环境将其转换为代码,将代码编写为汇编和汇编。中间步骤-的实现append
-可以在此处的编译器中找到。
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
如您所见,看不到CALL
对函数调用的语句append
。这是append
示例代码中调用的完整实现。用不同的参数另一呼叫将看起来不同(其他寄存器,取决于切片类型等不同的参数)。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句