Jadual Kandungan
Kesimpulan yang salah: Menggunakan penunjuk adalah lebih baik?
Menyalin struktur data yang besar
Kebolehubahan
Konsistensi API
mewakili nilai am
Mengapa saya memilih nilai?
Rumah pembangunan bahagian belakang Golang Adakah anda tahu bila hendak menggunakan penunjuk Go?

Adakah anda tahu bila hendak menggunakan penunjuk Go?

Sep 24, 2021 pm 03:08 PM
go penunjuk

Artikel ini ditulis oleh ruangan tutorial bahasa go untuk memperkenalkan kepada anda dalam keadaan bagaimana penunjuk Go (Go Pointer) digunakan, saya harap ia dapat membantu rakan-rakan memerlukan!

Adakah anda tahu bila hendak menggunakan penunjuk Go?

Penggunaan petunjuk dalam kod GO tidak mesra dengan orang baru, terutamanya apabila sukar untuk membezakan senario penggunaan.

Saya fikir salah satu salah tanggapan terbesar apabila menggunakan penunjuk ialah penunjuk dalam Go sangat serupa dengan penunjuk dalam C. Namun, itu tidak berlaku. Penunjuk tidak berfungsi dalam Go dengan cara yang sama seperti dalam C/C.

Artikel ini akan membincangkan cara menggunakan penunjuk Go dengan betul.

Kesimpulan yang salah: Menggunakan penunjuk adalah lebih baik?

Adalah diterima umum bahawa aplikasi akan berjalan lebih pantas apabila menggunakan penunjuk kerana ia mengelak daripada menyalin nilai sepanjang masa. Tidak menghairankan bahawa dalam Go kami mempunyai idea yang sama.

Walau bagaimanapun, hantaran penunjuk dalam Go biasanya lebih perlahan daripada hantaran nilai. Ini adalah akibat daripada Go menjadi bahasa kutipan sampah. Apabila anda menghantar penuding kepada fungsi, Go perlu melakukan analisis melarikan diri untuk menentukan sama ada pembolehubah harus disimpan pada timbunan atau timbunan. Ini sudah menambah beberapa overhed tambahan, tetapi sebaliknya pembolehubah boleh disimpan dalam timbunan. Apabila anda menyimpan pembolehubah dalam timbunan, anda juga kehilangan masa semasa GC sedang melaksanakan.

Ciri mudah Go ialah anda boleh menyemak tindakan analisis melarikan diri dengan melaksanakan arahan go build -gcflags="-m". Jika anda melakukan ini, Go akan memberitahu anda jika pembolehubah terlepas ke timbunan:

./main.go:44:20: greet ... argument does not escape
./main.go:44:21: greeting escapes to heap
./main.go:44:21: name escapes to heap
Salin selepas log masuk

Jika pembolehubah tidak terlepas ke timbunan, ia berada pada timbunan. Tindanan tidak memerlukan pemungut sampah untuk mengosongkan pembolehubah, ia hanya melakukan operasi push/pop.

Jika mana-mana kandungan diluluskan mengikut nilai, ia akan sentiasa diproses pada timbunan, yang tidak akan menyebabkan kutipan sampah di atas kepala. (GC akan dijalankan secara lalai. Kurang kandungan dalam timbunan bermakna GC kurang perlu dilakukan).

Sekarang anda tahu bahawa menggunakan penunjuk akan mengurangkan prestasi, jadi bilakah anda perlu menggunakan penunjuk?

Menyalin struktur data yang besar

Adakah penunjuk sentiasa berprestasi lebih teruk daripada pemindahan nilai? Itu jelas tidak berlaku. Penunjuk memainkan peranan apabila bekerja dengan struktur data yang besar. Ini boleh menyebabkan kos kutipan sampah diimbangi oleh kos penyalinan sejumlah besar data.

Apabila saya menyebut perkara ini, saya selalu ditanya 'berapa besarkah data besar itu'?

Saya rasa tiada nilai tetap di sini, apa-apa yang berkaitan dengan prestasi harus ditanda aras. Go mempunyai alat penanda aras berkuasa terbina dalam yang boleh dieksploitasi sepenuhnya

Kebolehubahan

Satu-satunya cara untuk mengubah suai parameter fungsi ialah dengan menghantar penunjuk. Secara lalai, pengubahsuaian kepada nilai dilakukan pada salinan. Oleh itu pengubahsuaian ini tidak boleh dicerminkan dalam fungsi yang memanggilnya.

Lihat kod berikut:

type person struct {
 name string
}func main() {
 p := person{"Richard"}
 rename(p)
 fmt.Println(p)
}func rename(p person) {
 p.name = "test"
}
Salin selepas log masuk

Outputnya ialah Richard kerana pengubahsuaian kepada orang dibuat pada salinannya. Jika anda ingin menukar nilai objek orang yang mendasari, anda perlu menggunakan penunjuk.

func main() {
 p := person{"Richard"}
 rename(&p)
 fmt.Println(p)
}func rename(p *person) {
 p.name = "test"
}
Salin selepas log masuk

Seperti di atas, keluarkan test. Kebolehubahan ialah situasi di mana penunjuk digunakan dalam Go. Sama ada ini adalah perkara yang baik untuk dibahaskan.

Konsistensi API

Gunakan penunjuk untuk mengekalkan nilai terkini. Ini memastikan API konsisten walaupun tidak semua kaedah mengubah nilainya.

Oleh itu, ini:

func (p *person) rename(s string) {
   p.name = s 
}func (p *person) printName() {
  fmt.Println(p.name)
}
Salin selepas log masuk

lebih baik daripada

func (p *person) rename(s string) {
   p.name = s 
}func (p person) printName() {
  fmt.Println(p.name)
}
Salin selepas log masuk

walaupun tidak perlu menggunakan penunjuk dalam printName untuk konsistensi. Tetapi ini akan menjadikan API lebih mudah dan mengelak daripada mengingati di mana rujukan diperlukan.

mewakili nilai am

yang hilang, apabila digunakan, mempunyai nilai lalai sifar. Tetapi terdapat senario di mana anda perlu tahu bahawa ada sesuatu yang hilang atau mempunyai nilai yang tidak diisi. Sebagai contoh, struktur mengandungi skor ujian pelajar Jika struktur kosong dan mempunyai skor 0, adakah ia bermakna pelajar itu tidak berjaya dalam ujian, atau tidak mengambil ujian langsung? Nilai sifar lalai untuk penunjuk

ialah penunjuk nil, yang bermaksud tiada nilai ditetapkan. Keperluan ini juga boleh dilaksanakan seperti berikut:

type exam struct {
    score   int
    present bool
}
Salin selepas log masuk

Gunakan medan present yang berasingan untuk menunjukkan pelajar tidak mengambil peperiksaan.

Mengapa saya memilih nilai?

Ini agak subjektif. Orang yang berbeza mempunyai pemahaman yang berbeza tentang pengaturcaraan, jadi kami tidak perlu mempunyai konsep yang sama

Saya percaya adalah masuk akal untuk mempunyai nilai lalai dalam nilai Go sebanyak mungkin. Ini mungkin tidak berfungsi dalam setiap keadaan, tetapi dalam kes saya ia menyelamatkan saya daripada kemalangan besar. Menggunakan nilai dan bukannya penunjuk tidak akan menyebabkan "kesilapan berjuta dolar" Tony Hoare disebabkan oleh penunjuk nol.

Nilai lalai sifar berguna untuk mengelakkan banyak pengisytiharan.

另一个好处是易变性造成的问题比它解决的问题多的得多。易变性给函数带来的副作用同时使得调试变得更加困难。 通过让函数返回修改之后的结构体,可以避免这种突变。

重写之前的例子

func main() {
 p := person{"richard"}
 p = rename(p)
 fmt.Println(p)
}func rename(p person) person {
 p.name = "test"
 return p
}
Salin selepas log masuk

这也是 append 如何工作的,所以并不陌生。

x := []int{1,2}
x = append(x, 3)
x = append(x, 4)
Salin selepas log masuk

鉴于指针的安全性,和值处理比指针处理更快,使用指针需要反复斟酌。

原文地址:https://medium.com/@meeusdylan/when-to-use-pointers-in-go-44c15fe04eac

译文地址:https://learnku.com/go/t/60923

Atas ialah kandungan terperinci Adakah anda tahu bila hendak menggunakan penunjuk Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn

Alat AI Hot

Undresser.AI Undress

Undresser.AI Undress

Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover

AI Clothes Remover

Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool

Undress AI Tool

Gambar buka pakaian secara percuma

Clothoff.io

Clothoff.io

Penyingkiran pakaian AI

AI Hentai Generator

AI Hentai Generator

Menjana ai hentai secara percuma.

Alat panas

Notepad++7.3.1

Notepad++7.3.1

Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina

SublimeText3 versi Cina

Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1

Hantar Studio 13.0.1

Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6

Dreamweaver CS6

Alat pembangunan web visual

SublimeText3 versi Mac

SublimeText3 versi Mac

Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Bagaimana untuk menghantar mesej Go WebSocket? Bagaimana untuk menghantar mesej Go WebSocket? Jun 03, 2024 pm 04:53 PM

Dalam Go, mesej WebSocket boleh dihantar menggunakan pakej gorila/soket web. Langkah khusus: Wujudkan sambungan WebSocket. Hantar mesej teks: Panggil WriteMessage(websocket.TextMessage,[]bait("Mesej")). Hantar mesej binari: panggil WriteMessage(websocket.BinaryMessage,[]bait{1,2,3}).

Bagaimana untuk memadankan cap masa menggunakan ungkapan biasa dalam Go? Bagaimana untuk memadankan cap masa menggunakan ungkapan biasa dalam Go? Jun 02, 2024 am 09:00 AM

Dalam Go, anda boleh menggunakan ungkapan biasa untuk memadankan cap masa: susun rentetan ungkapan biasa, seperti yang digunakan untuk memadankan cap masa ISO8601: ^\d{4}-\d{2}-\d{2}T \d{ 2}:\d{2}:\d{2}(\.\d+)?(Z|[+-][0-9]{2}:[0-9]{2})$ . Gunakan fungsi regexp.MatchString untuk menyemak sama ada rentetan sepadan dengan ungkapan biasa.

Perbezaan antara bahasa Golang dan Go Perbezaan antara bahasa Golang dan Go May 31, 2024 pm 08:10 PM

Bahasa Go dan Go adalah entiti yang berbeza dengan ciri yang berbeza. Go (juga dikenali sebagai Golang) terkenal dengan kesesuaiannya, kelajuan penyusunan pantas, pengurusan memori dan kelebihan merentas platform. Kelemahan bahasa Go termasuk ekosistem yang kurang kaya berbanding bahasa lain, sintaks yang lebih ketat dan kekurangan penaipan dinamik.

Bagaimana untuk mengelakkan kebocoran memori dalam pengoptimuman prestasi teknikal Golang? Bagaimana untuk mengelakkan kebocoran memori dalam pengoptimuman prestasi teknikal Golang? Jun 04, 2024 pm 12:27 PM

Kebocoran memori boleh menyebabkan memori program Go terus meningkat dengan: menutup sumber yang tidak lagi digunakan, seperti fail, sambungan rangkaian dan sambungan pangkalan data. Gunakan rujukan yang lemah untuk mengelakkan kebocoran memori dan objek sasaran untuk pengumpulan sampah apabila ia tidak lagi dirujuk dengan kuat. Menggunakan go coroutine, memori tindanan coroutine akan dikeluarkan secara automatik apabila keluar untuk mengelakkan kebocoran memori.

Panduan untuk menguji unit fungsi serentak Go Panduan untuk menguji unit fungsi serentak Go May 03, 2024 am 10:54 AM

Unit menguji fungsi serentak adalah penting kerana ini membantu memastikan kelakuan mereka yang betul dalam persekitaran serentak. Prinsip asas seperti pengecualian bersama, penyegerakan dan pengasingan mesti dipertimbangkan semasa menguji fungsi serentak. Fungsi serentak boleh diuji unit dengan mensimulasikan, menguji keadaan perlumbaan dan mengesahkan keputusan.

Analisis mendalam petunjuk dan rujukan dalam C++ untuk mengoptimumkan penggunaan memori Analisis mendalam petunjuk dan rujukan dalam C++ untuk mengoptimumkan penggunaan memori Jun 02, 2024 pm 07:50 PM

Dengan menggunakan penunjuk dan rujukan, penggunaan memori dalam C++ boleh dioptimumkan: Penunjuk: menyimpan alamat pembolehubah lain dan boleh menghala ke pembolehubah berbeza, menjimatkan memori, tetapi mungkin menjana penunjuk liar. Rujukan: Diasingkan kepada pembolehubah lain, sentiasa menunjuk kepada pembolehubah yang sama, tidak menjana penunjuk liar dan sesuai untuk parameter fungsi. Mengoptimumkan penggunaan memori boleh meningkatkan kecekapan dan prestasi kod dengan mengelakkan salinan yang tidak diperlukan, mengurangkan peruntukan memori dan menjimatkan ruang.

Bagaimana untuk menggunakan pembungkus ralat Golang? Bagaimana untuk menggunakan pembungkus ralat Golang? Jun 03, 2024 pm 04:08 PM

Dalam Golang, pembalut ralat membolehkan anda membuat ralat baharu dengan menambahkan maklumat kontekstual kepada ralat asal. Ini boleh digunakan untuk menyatukan jenis ralat yang dilemparkan oleh perpustakaan atau komponen yang berbeza, memudahkan penyahpepijatan dan pengendalian ralat. Langkah-langkahnya adalah seperti berikut: Gunakan fungsi ralat. Balut untuk membalut ralat asal kepada ralat baharu. Ralat baharu mengandungi maklumat kontekstual daripada ralat asal. Gunakan fmt.Printf untuk mengeluarkan ralat yang dibalut, memberikan lebih konteks dan kebolehtindakan. Apabila mengendalikan pelbagai jenis ralat, gunakan fungsi ralat. Balut untuk menyatukan jenis ralat.

Bagaimana untuk mencipta Goroutine yang diutamakan dalam Go? Bagaimana untuk mencipta Goroutine yang diutamakan dalam Go? Jun 04, 2024 pm 12:41 PM

Terdapat dua langkah untuk mencipta Goroutine keutamaan dalam bahasa Go: mendaftarkan fungsi penciptaan Goroutine tersuai (langkah 1) dan menentukan nilai keutamaan (langkah 2). Dengan cara ini, anda boleh mencipta Goroutine dengan keutamaan yang berbeza, mengoptimumkan peruntukan sumber dan meningkatkan kecekapan pelaksanaan.

See all articles