Saya baru untuk Go dan saya mengalami sedikit disonansi congitive antara pemrograman berbasis-gaya-C di mana variabel otomatis tinggal di tumpukan dan mengalokasikan memori yang hidup di heap dan dan pemrograman berbasis-tumpukan-gaya-Python di mana Satu-satunya hal yang hidup di stack adalah referensi / pointer ke objek di heap.
Sejauh yang saya tahu, dua fungsi berikut memberikan hasil yang sama:
func myFunction() (*MyStructType, error) {
var chunk *MyStructType = new(HeaderChunk)
...
return chunk, nil
}
func myFunction() (*MyStructType, error) {
var chunk MyStructType
...
return &chunk, nil
}
yaitu mengalokasikan struct baru dan mengembalikannya.
Jika saya menulisnya di C, yang pertama akan meletakkan objek di tumpukan dan yang kedua akan meletakkannya di tumpukan. Yang pertama akan mengembalikan pointer ke heap, yang kedua akan mengembalikan pointer ke stack, yang akan menguap pada saat fungsi kembali, yang akan menjadi Bad Thing.
Jika saya menulisnya dengan Python (atau banyak bahasa modern lainnya kecuali C #) contoh 2 tidak akan mungkin.
Saya mendapatkan bahwa sampah Go mengumpulkan kedua nilai, sehingga kedua bentuk di atas baik-baik saja.
Kutipan:
Perhatikan bahwa, tidak seperti dalam C, tidak apa-apa untuk mengembalikan alamat variabel lokal; penyimpanan yang terkait dengan variabel bertahan setelah fungsi kembali. Bahkan, mengambil alamat dari literal komposit mengalokasikan contoh baru setiap kali dievaluasi, sehingga kita dapat menggabungkan dua baris terakhir ini.
Tapi itu menimbulkan beberapa pertanyaan.
1 - Dalam contoh 1, struct dideklarasikan pada heap. Bagaimana dengan contoh 2? Apakah itu dideklarasikan pada stack dengan cara yang sama dengan di C atau apakah ia ikut tumpukan juga?
2 - Jika contoh 2 dideklarasikan pada stack, bagaimana itu tetap tersedia setelah fungsi kembali?
3 - Jika contoh 2 sebenarnya dideklarasikan di heap, bagaimana mungkin struct disahkan oleh nilai daripada dengan referensi? Apa gunanya petunjuk dalam kasus ini?
Dalam kedua kasus, implementasi Go saat ini akan mengalokasikan memori untuk
struct
tipeMyStructType
pada heap dan mengembalikan alamatnya. Fungsinya setara; sumber asm kompiler adalah sama.Semua fungsi dan parameter pengembalian dilewatkan oleh nilai. Nilai parameter pengembalian dengan tipe
*MyStructType
adalah alamat.sumber
Menurut FAQ Go :
sumber
Sumber: http://devs.cloudimmunity.com/gotchas-and-common-mistakes-in-go-golang/index.html#stack_heap_vars
sumber
Function1 dan Function2 mungkin fungsi inline. Dan variabel return tidak akan lepas. Tidak perlu mengalokasikan variabel di heap.
Contoh kode saya:
Menurut output cmd:
keluaran:
Jika kompiler cukup pintar, F1 () F2 () F3 () mungkin tidak dipanggil. Karena tidak ada artinya.
Tidak peduli apakah suatu variabel dialokasikan pada heap atau stack, gunakan saja. Lindungi dengan mutex atau saluran jika perlu.
sumber