


Bangunan Pertanyaan SQL yang boleh dikekalkan dengan Golang
Sebarang aplikasi yang berfungsi dengan pertanyaan SQL boleh mendapat manfaat daripada menggunakan pembina pertanyaan untuk meningkatkan kebolehbacaan kod, kebolehselenggaraan dan keselamatan. Malah, terdapat banyak perpustakaan berbeza yang melakukan perkara itu di Golang. Di Vaunt, kami mencuba pelbagai pilihan sebelum akhirnya memutuskan untuk menciptanya sendiri. Akhirnya, kami mahukan sesuatu yang selamat dan menyediakan penggantian berubah-ubah untuk menghalang suntikan SQL sambil masih boleh dibaca dan boleh mempunyai pernyataan bersyarat. Jadi kami mencipta perpustakaan baharu yang dipanggil tqla, dikeluarkan dan diumumkan lewat tahun lepas. Anda boleh membaca lebih lanjut mengenainya dalam artikel ini.
Sebelum kami membina tqla, kami terutamanya menggunakan Tupai untuk logik pembinaan pertanyaan SQL kami—dan kami sangat mengesyorkannya. Kami masih menggunakan Squirrel di beberapa kawasan tetapi secara beransur-ansur mula menggantikan dan melaksanakan logik pembinaan pertanyaan baharu dengan tqla. Kami telah menemui banyak keadaan di mana tqla telah meningkatkan keupayaan kami untuk mengekalkan kod kami dan menyelesaikan masalah yang kami hadapi semasa menggunakan pembina pernyataan lain.
Kes Penggunaan Dunia Nyata
Di Vaunt, kami baru-baru ini menjalani pemindahan pangkalan data daripada CockroachDB ke TiDB. Walaupun CockroachDB berprestasi dan boleh dipercayai, kami akhirnya menghadapi keputusan untuk menambah techstack kami untuk menyokong pangkalan data OLAP. Keperluan untuk ini adalah untuk menyokong beban kerja analisis kami pada produk cerapan komuniti sumber terbuka kami. Untuk memastikan jejak teknologi kami kecil, kami memutuskan untuk bergerak ke hadapan dengan TiDB dan memanfaatkan seni bina HTAP pangkalan data.
CockroachDB sebahagian besarnya serasi dengan PostgreSQL, dan kami menggunakan sintaks PostgreSQL untuk kebanyakan pertanyaan SQL kami. Untuk bertukar kepada TiDB, kami terpaksa menukar beberapa jadual kami dan mengemas kini pertanyaan untuk menggunakan sintaks MySQL. Di beberapa lokasi semasa penghijrahan, kami mendapati bahawa kami menggunakan pernyataan binaan pertanyaan bersyarat secara tidak wajar dan tidak mempunyai ujian yang sesuai untuk mengetahui bahawa pernyataan tersebut dijana secara tidak betul.
Demonstrasi
Dalam README Squirrel, terdapat contoh cara anda boleh menggunakan binaan pertanyaan bersyarat untuk mengemas kini pernyataan dengan penapis pilihan:
if len(q) > 0 { users = users.Where("name LIKE ?", fmt.Sprint("%", q, "%")) }
Berikut ialah contoh sebenar tetapi ringkas tentang cara kami mengemas kini salah satu pertanyaan kami untuk menyertai jadual secara bersyarat dan menambah penapis pilihan:
psql := squirrel.StatementBuilder.PlaceholderFormat(squirrel.Question) statementBuilder := psql.Select(`i.id`). From("vaunt.installations i"). Where(`entity_name = ?`, name) if len(provider) > 0 { statementBuilder.Where(`provider = ?`, provider) } if len(repo) > 0 { statementBuilder.Join(`repositories as r on JSON_CONTAINS(i.repositories, CONCAT('["', r.id, '"]'))`) statementBuilder.Where(`r.name = ?`, repo) }
Bolehkah anda melihat isu dengan kod itu? Jika tidak, jangan risau—ia adalah sesuatu yang terlepas daripada ulasan kod kami sendiri sehingga kami menjalankan ujian kami.
Isunya di sini ialah kami terlupa untuk mengemas kini pembangun penyata dengan hasil fungsi pembina. Sebagai contoh, penapis keadaan pembekal sebaliknya harus membaca:
if len(provider) > 0 { statementBuilder = statementBuilder.Where(`provider = ?`, provider) }
Ini adalah kesilapan yang agak mudah untuk dilakukan dan mudah ditangkap dengan kes ujian yang mencukupi, tetapi kerana ia bukan kod teknikal yang tidak sah, ia mungkin mengambil sedikit masa untuk menyedari perkara yang berlaku dengan segera.
Satu lagi isu kebolehbacaan dengan persediaan ini ialah gabungan bersyarat dipisahkan daripada pernyataan pilih awal. Kami boleh menyusun semula pembina untuk meletakkan setiap bahagian di tempat yang sepatutnya, tetapi ia memerlukan berbilang semakan pernyataan bersyarat pendua dan masih mengalami beberapa isu kebolehbacaan.
Menggunakan tqla
Demonstrasi di atas menggunakan Tupai sejak itu telah ditulis semula, dan persamaan dalam tqla kelihatan seperti ini:
t, err := tqla.New(tqla.WithPlaceHolder(tqla.Question)) if err != nil { return nil, err } query, args, err := t.Compile(` SELECT i.id FROM vaunt.installations as i {{ if .Repo }} JOIN vaunt.repositories as r on JSON_CONTAINS(i.repositories, CONCAT('["', r.id, '"]'), '$') {{ end }} WHERE entity_name = {{ .Name}} {{ if .Provider }} AND i.provider = {{ .Provider }} {{ end }} {{ if .Repo }} AND r.name = {{ .Repo }} {{ end }} `, data) if err != nil { return nil, err }
Seperti yang anda lihat, sintaks templat untuk tqla menjadikan menggabungkan klausa bersyarat sangat mudah. Tqla secara automatik menggantikan pembolehubah yang kami tetapkan dengan ruang letak kami yang ditentukan dan menyediakan hujah yang boleh kami gunakan dengan pemacu sql kami untuk melaksanakan pernyataan.
Serupa dengan Squirrel, pendekatan membina pernyataan ini mudah diuji, kerana kami boleh mencipta set objek data yang berbeza untuk dihantar kepada pembina templat dan mengesahkan output.
Anda dapat melihat bahawa kami boleh menambah soalan bersyarat dengan mudah di tempat yang paling sesuai. Sebagai contoh, di sini kami mempunyai SERTAI bersyarat terus selepas pernyataan FROM—dan walaupun kami masih mempunyai beberapa semakan syarat, ia tidak terlalu merumitkan templat.
Fungsi Tersuai
Ciri tqla lain yang bagus yang membantu meningkatkan kebolehselenggaraan pembangun sql kami ialah keupayaan untuk menentukan fungsi tersuai yang boleh kami gunakan dalam templat untuk mengabstrak beberapa logik transformasi.
Berikut ialah contoh cara kami menggunakan fungsi untuk menukar masa Golang. Nilai masa menjadi sql.NullTime untuk membolehkan kami melakukan sisipan dengan objek data kami tanpa perlu menukarnya terlebih dahulu:
funcs := template.FuncMap{ "time": func(t time.Time) sql.NullTime { if t.IsZero() { return sql.NullTime{Valid: false} } return sql.NullTime{Time: t, Valid: true} }, } t, err := tqla.New(tqla.WithPlaceHolder(tqla.Question), tqla.WithFuncMap(funcs)) if err != nil { return err }
Dengan fungsi ini yang ditakrifkan dalam peta funcs tqla kami, kami kini boleh menggunakannya secara bebas dalam templat pertanyaan kami dengan memberikannya parameter daripada objek data iaitu medan masa.Masa. Kita juga boleh memanggil fungsi ini beberapa kali dalam templat yang sama dengan medan yang berbeza.
Here is a simplified example:
statement, args, err := t.Compile(` INSERT INTO events (name, created_at, merged_at, closed_at) VALUES ( {{ .Name }}, {{ time .CreatedAt }}, {{ time .MergedAt }}, {{ time .ClosedAt }} )`, eventData)
Conclusion
In conclusion, we believe that using tqla can help improve the maintainability of query building logic while offering some powerful utility for creating dynamic queries. The simplicity of the template structure allows for clean code readability and can make it faster to debug any potential errors.
We made tqla open source to share this library in hopes that it provides a good option for other users wanting a simple, maintainable, and secure way to build sql queries in many different types of applications.
If you are interested, please check out the repository and give it a star if it helps you in any way. Feel free to make any feature requests or bug reports!
We are always open to receiving feedback and contributions.
To stay in the loop on future development, follow us on X or join our Discord!
Atas ialah kandungan terperinci Bangunan Pertanyaan SQL yang boleh dikekalkan dengan Golang. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Alat AI Hot

Undress AI Tool
Gambar buka pakaian secara percuma

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

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

Clothoff.io
Penyingkiran pakaian AI

Video Face Swap
Tukar muka dalam mana-mana video dengan mudah menggunakan alat tukar muka AI percuma kami!

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)

Ia tidak sukar untuk membina pelayan web yang ditulis dalam Go. Inti terletak pada menggunakan pakej NET/HTTP untuk melaksanakan perkhidmatan asas. 1. Gunakan NET/HTTP untuk memulakan pelayan yang paling mudah: fungsi pemprosesan mendaftar dan mendengar port melalui beberapa baris kod; 2. 3. Amalan Umum: Routing Kumpulan oleh Modul Fungsional, dan gunakan perpustakaan pihak ketiga untuk menyokong padanan kompleks; 4. Perkhidmatan Fail Statik: Sediakan fail HTML, CSS dan JS melalui http.fileserver; 5. Prestasi dan Keselamatan: Aktifkan HTTPS, hadkan saiz badan permintaan, dan tetapkan masa tamat untuk meningkatkan keselamatan dan prestasi. Selepas menguasai perkara -perkara utama ini, lebih mudah untuk mengembangkan fungsi.

Inti pemprosesan audio dan video terletak pada pemahaman proses asas dan kaedah pengoptimuman. 1. Proses asas termasuk pengambilalihan, pengekodan, penghantaran, penyahkodan dan main balik, dan setiap pautan mempunyai kesukaran teknikal; 2. Masalah biasa seperti penyimpangan audio dan video, kelewatan lag, bunyi bunyi, gambar kabur, dan lain -lain boleh diselesaikan melalui pelarasan segerak, pengoptimuman pengekodan, modul pengurangan hingar, pelarasan parameter, dan sebagainya; 3. Adalah disyorkan untuk menggunakan FFMPEG, OpenCV, WebRTC, GSTREAMER dan alat lain untuk mencapai fungsi; 4. Dari segi pengurusan prestasi, kita harus memberi perhatian kepada pecutan perkakasan, penetapan kadar bingkai resolusi yang munasabah, masalah konvensyen dan masalah kebocoran memori. Menguasai perkara utama ini akan membantu meningkatkan kecekapan pembangunan dan pengalaman pengguna.

Tujuan Select Plus Default adalah untuk membolehkan Pilih untuk melakukan tingkah laku lalai apabila tiada cawangan lain yang bersedia untuk mengelakkan penyekatan program. 1. Apabila menerima data dari saluran tanpa menyekat, jika saluran kosong, ia akan terus memasuki cawangan lalai; 2. Dalam kombinasi dengan masa. Selepas atau ticker, cuba hantar data dengan kerap. Jika saluran penuh, ia tidak akan menyekat dan melangkau; 3. Mencegah kebuntuan, elakkan program terperangkap apabila tidak pasti sama ada saluran ditutup; Apabila menggunakannya, sila ambil perhatian bahawa cawangan lalai akan dilaksanakan dengan serta -merta dan tidak boleh disalahgunakan, dan lalai dan kes saling eksklusif dan tidak akan dilaksanakan pada masa yang sama.

Cara yang paling berkesan untuk menulis Kubernetesoperator adalah untuk menggunakan Go untuk menggabungkan Kubebuilder dan pengawal-runtime. 1. Memahami corak pengendali: Tentukan sumber tersuai melalui CRD, tulis pengawal untuk mendengar perubahan sumber dan lakukan gelung perdamaian untuk mengekalkan keadaan yang diharapkan. 2. Gunakan Kubebuilder untuk memulakan projek dan membuat API untuk menghasilkan CRD, pengawal dan konfigurasi secara automatik. 3. Tentukan spec dan struktur status CRD dalam API/V1/MYAPP_TYPES.GO, dan menjalankan makeManifests untuk menjana cRDYAML. 4. Daftar masuk dalam pengawal

Bagaimana dengan cepat melaksanakan contoh Restapi yang ditulis dalam GO? Jawapannya adalah menggunakan perpustakaan standard Net/HTTP, yang boleh diselesaikan mengikut tiga langkah berikut: 1. Sediakan struktur projek dan memulakan modul; 2. Tentukan struktur data dan fungsi pemprosesan, termasuk mendapatkan semua data, mendapatkan data tunggal berdasarkan ID, dan membuat data baru; 3. Daftar laluan dalam fungsi utama dan mulakan pelayan. Seluruh proses tidak memerlukan perpustakaan pihak ketiga. Fungsi Restapi Asas dapat direalisasikan melalui perpustakaan standard dan boleh diuji melalui penyemak imbas atau pos.

Langkah-langkah pemasangan Golangci-lint adalah: 1. Pasang menggunakan pemasangan binari atau perintah goinstall; 2. Sahkan sama ada pemasangan berjaya; Kaedah konfigurasi termasuk: 3. Buat fail .golangci.yml untuk membolehkan/melumpuhkan linter, menetapkan laluan pengecualian, dan sebagainya; Kaedah integrasi adalah: 4. Tambah langkah -langkah lint dalam CI/CD (seperti githubactions) untuk memastikan bahawa pemeriksaan LINT secara automatik dijalankan untuk setiap penyerahan dan PR.

Gunakan perintah terbina dalam getest untuk menjana data liputan: Run Getest-Cover./... untuk memaparkan peratusan liputan setiap pakej, atau gunakan getest-coverprofile = liputan.out. Mengintegrasikan Laporan Liputan di CI: Buat fail liputan.out, dan muat naik analisis melalui alat pihak ketiga seperti codecov atau coveralls, sebagai contoh, menggunakan curl-data-binary@coverage.o

Untuk mengurangkan peruntukan timbunan fungsi laluan kritikal di GO, empat kaedah boleh diambil: 1. Gunakan pembolehubah timbunan untuk mengelakkan melarikan diri; 2. Pra-memperuntukkan dan menggunakan semula objek; 3. Elakkan penulisan melarikan diri tersirat; 4. Gunakan alat untuk mengesahkan melarikan diri. Khususnya, ia termasuk mengelakkan penunjuk pembolehubah tempatan yang kembali, menggunakan jenis nilai untuk mengurangkan pelarian, pra-memperuntukkan kapasiti kepingan, menggunakan sync.pool ke objek cache, mengelakkan penutupan untuk menangkap struktur besar, tidak menetapkan jenis antara muka, dan memeriksa titik melarikan diri melalui -gcflags = -m, dengan itu mengurangkan tekanan GC dan meningkatkan prestasi.
