


Program Go terlalu besar. Bolehkah kita menggunakan pengamulaan malas?
Dalam pembangunan berterusan syarikat, kebanyakannya adalah unit yang besar pada mulanya, dan transformasinya perlahan Sebuah gudang akan digunakan selama lebih daripada sepuluh tahun, dan skala gudang itu pada asasnya a proses peningkatan berterusan.
Salah satu impaknya ialah saiz aplikasi yang dibungkus semakin besar dan saya tidak tahu di mana ia digunakan... Cadangan yang akan dibincangkan hari ini "proposal: bahasa: lazy init import ke mungkin import tanpa kesan sampingan [1]" adalah berkaitan dengan ini.
Cadangan
Latar Belakang
Mari kita perhatikan kod Go yang sangat mudah dan kajinya. Kod berikut:
package main import _ "crypto/x509" func main() {}
Program Go ini hanya mempunyai 3 baris kod dan tidak kelihatan seperti apa-apa. Adakah ini sebenarnya berlaku?
Kita boleh melaksanakan arahan berikut untuk melihat proses pemula:
$ go build --ldflags=--dumpdep main.go 2>&1 | grep inittask
Hasil output:
runtime.main -> runtime..inittask runtime.main -> main..inittask main..inittask -> crypto/x509..inittask crypto/x509..inittask -> bytes..inittask crypto/x509..inittask -> crypto/sha256..inittask crypto/x509..inittask -> encoding/pem..inittask crypto/x509..inittask -> errors..inittask crypto/x509..inittask -> sync..inittask crypto/x509..inittask -> crypto/aes..inittask crypto/x509..inittask -> crypto/cipher..inittask crypto/x509..inittask -> crypto/des..inittask ... context..inittask -> context.init.0 vendor/golang.org/x/net/dns/dnsmessage..inittask -> vendor/golang.org/x/net/dns/dnsmessage.init vendor/golang.org/x/net/route..inittask -> vendor/golang.org/x/net/route.init vendor/golang.org/x/net/route..inittask -> vendor/golang.org/x/net/route.init.0 ...
Program ini sebenarnya memulakan banyak pakej perisian (perpustakaan standard, pakej pihak ketiga, dll.). Ini menukar saiz pakej daripada 1.3 MB standard kepada 2.3 MB.
Pada skala tertentu, semua orang percaya bahawa impak ini sangat mahal. Kerana anda dapat melihat bahawa program Go dengan hanya 3 baris tidak melakukan apa-apa yang besar.
Program yang sensitif terhadap prestasi permulaan akan menjadi lebih tidak selesa Program biasa juga akan memasuki kitaran ganas dari semasa ke semasa, dan permulaan akan menjadi lebih perlahan daripada biasa.
Penyelesaian
Kami akan melihat penyelesaian bersama-sama dengan cadangan lain "proposal: spec: Go 2: allow manual control over imported package initialization[2]".
Idea terasnya ialah memperkenalkan lazy initialization (lazy init), yang juga sering dipanggil lazy loading dalam industri. Maksudnya, import sebenar dilakukan apabila perlu, dan permulaan selesai apabila pakej tidak diperkenalkan.
Arah pengoptimuman: terutamanya menambahkan pengisytiharan pemula malas selepas mengimport laluan pakej, seperti anotasi go:lazyinit atau go:deferred yang dinyatakan di bawah. Tunggu sehingga program benar-benar digunakan sebelum memulakannya secara rasmi.
1、go:lazyinit 的例子:
package main import ( "crypto/x509" // go:lazyinit "fmt" ) func main() {...}
2、go:deferred 的例子:
package main import ( _ "github.com/eddycjy/core" // go:deferred _ "github.com/eddycjy/util" // go:deferred ) func main() { if os.Args[1] != "util" { // 现在要使用这个包,开始初始化 core, err := runtime.InitDeferredImport("github.com/some/module/core") ... } ... }
以此来实现,可以大大提高启动性能。
讨论
实际上在大多数的社区讨论中,对这个提案是又爱又恨。因为它似乎又有合理的诉求,但细思似乎又会发现完全不对劲。
这个提案的背景和解决方案,是治标不治本的。因为根本原因是:许多库滥用了 init 函数,让许多不必要的东西都初始化了。

Go 核心开发团队认为让库作者去修复这些库,而不是让 Go 来 “解决” 这些问题。如果支持惰性初始化,也会为这些低质量库的作者提供继续这样做的借口。
似曾相识的感觉
在写这篇文章时,我想起了 Go 的依赖管理(Go modules),其有一个设计是基于语义化版本的规范。
如下图

版本格式为 “主版本号.次版本号.修订号”,版本号的递增规则如下:
主版本号:当你做了不兼容的 API 修改。 次版本号:当你做了向下兼容的功能性新增。 修订号:当你做了向下兼容的问题修正。
Go modules 的原意是软件库都遵守这个规范,因此内部会有最小版本选择的逻辑。
也就是一个模块往往依赖着许多其它许许多多的模块,并且不同的模块在依赖时很有可能会出现依赖同一个模块的不同版本,Go 会把版本清单都整理出来,最终得到一个构建清单。
如下图:

Anda akan mendapati bahawa versi pergantungan terakhir yang dibina berkemungkinan tidak konsisten dengan yang dijangkakan, yang membawa kepada banyak masalah perniagaan. Yang paling klasik ialah masalah keserasian berbilang versi grpc-go, protoc-go, etcd, yang membuatkan ramai orang menderita.
Reka bentuk pasukan Go di kawasan ini agak ideal, dan Cao Da juga mengklasifikasikannya sebagai salah satu daripada tujuh dosa maut modul Go. Fungsi init pakej perisian mempunyai banyak masalah dengan permulaan rawak, yang juga agak biasa.
Ringkasan
Penyelesaian (cadangan) untuk masalah ini masih dalam perbincangan.
Bagaimana pula dengan memperkenalkan pemula malas, apa pendapat anda? Selamat tinggalkan mesej dan berbincang di ruangan komen.
Atas ialah kandungan terperinci Program Go terlalu besar. Bolehkah kita menggunakan pengamulaan malas?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undresser.AI Undress
Apl berkuasa AI untuk mencipta foto bogel yang realistik

AI Clothes Remover
Alat AI dalam talian untuk mengeluarkan pakaian daripada foto.

Undress AI Tool
Gambar buka pakaian secara percuma

Clothoff.io
Penyingkiran pakaian AI

AI Hentai Generator
Menjana ai hentai secara percuma.

Artikel Panas

Alat panas

Notepad++7.3.1
Editor kod yang mudah digunakan dan percuma

SublimeText3 versi Cina
Versi Cina, sangat mudah digunakan

Hantar Studio 13.0.1
Persekitaran pembangunan bersepadu PHP yang berkuasa

Dreamweaver CS6
Alat pembangunan web visual

SublimeText3 versi Mac
Perisian penyuntingan kod peringkat Tuhan (SublimeText3)

Topik panas



Dalam Go, kitaran hayat fungsi termasuk definisi, pemuatan, pemautan, pemulaan, panggilan dan skop pembolehubah dibahagikan kepada tahap fungsi dan tahap blok Pembolehubah dalam fungsi boleh dilihat secara dalaman, manakala pembolehubah dalam blok hanya kelihatan dalam blok .

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.

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}).

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.

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.

Lihat dokumentasi fungsi Go menggunakan IDE: Tuding kursor pada nama fungsi. Tekan kekunci pintas (GoLand: Ctrl+Q; VSCode: Selepas memasang GoExtensionPack, F1 dan pilih "Go:ShowDocumentation").

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.

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.
