Możemy łatwo spojrzeć na skompilowany kod, aby potwierdzić, co dzieje się za kulisami.
Rozważmy następujący fragment:
func f() (a, b byte) {
return 'x', 'y'
}
func main() {
a, b := f()
println(a, b)
}
Gdybyśmy demontować utworzonego pliku binarnego ELF, zobaczysz coś takiego (inline został wyłączony więc mogliśmy zobaczyć wywołanie dzieje):
0000000000400c00 <main.f>:
400c00: c6 44 24 08 78 movb $0x78,0x8(%rsp)
400c05: c6 44 24 09 79 movb $0x79,0x9(%rsp)
400c0a: c3 retq
0000000000400c10 <main.main>:
(...)
400c25: 48 83 ec 10 sub $0x10,%rsp
400c29: e8 d2 ff ff ff callq 400c00 <main.f>
400c2e: 48 0f b6 1c 24 movzbq (%rsp),%rbx
400c33: 48 89 d8 mov %rbx,%rax
400c36: 48 0f b6 5c 24 01 movzbq 0x1(%rsp),%rbx
(...)
Tak więc f
po prostu umieszcza wynikowe bajty w stosie, a main
odbiera je i umieszcza w rejestrach roboczych. Inny kompilator może również wybrać przekazywanie tych wartości pomiędzy dwoma zakresami bezpośrednio do rejestrów.
Wszystko to jest podobne do tego, co zrobiłby kompilator dla języka C, z wyjątkiem tego, że specyfikacja definiuje tylko jedną wartość zwracaną.
nie, po prostu zwraca dwie wartości, a nie krotkę. Dlaczego normalne jest zwracanie wartości 1, ale nie 2? –
Jestem po prostu ciekawy. Nie znalazłem 1 powrotu normalnego. Próbuję tylko zrozumieć, jak powraca. –