Gesaan dan konteks
Satu perkhidmatan membaca hos dan port daripada konfigurasi dan menghantar fmt.Sprintf("%s:%d", host, port) kepada net.Dial. Ujian IPv4 berjaya, tetapi persekitaran pengeluaran mendedahkan IPv6, alamat link-local dan penghuraian port yang salah bentuk. Betulkan pelaksanaan dalam Go 1.25, terangkan net.JoinHostPort, SplitHostPort, pengecam zon dan sempadan pengesahan input, serta bincangkan penganalisis go vet hostport yang baharu. Kemahiran teras ialah pengaturcaraan rangkaian mudah alih, jadi ini adalah soalan coding.
Perkara yang dinilai oleh penemu duga
Pertama, sama ada anda menyedari bahawa teks IPv6 mengandungi berbilang titik bertindih, menjadikan penggabungan ringkas seperti 2001:db8::1:443 kabur.
Kedua, sama ada anda menggunakan pustaka standard untuk menambah kurungan mengikut sintaks alamat rangkaian dan bukannya percabangan tulisan tangan.
Ketiga, sama ada anda membezakan rentetan hos, pengecam zon, rentetan port dan autoriti lengkap supaya kurungan dan penghuraian tidak diduplikasi.
Keempat, sama ada ujian dan ralat meliputi IPv4, IPv6, %zone, hos kosong dan port yang tidak sah.
Kelima, sama ada go vet digunakan sebagai isyarat manakala semakan kod dan ujian sambungan sebenar mengesahkan pembetulan tersebut.
Soalan untuk dijelaskan terlebih dahulu
- Adakah
hostmerupakan IP kosong, nama DNS, autoriti berakar kurungan atau campuran? - Adakah port tersebut suatu integer, rentetan atau nama perkhidmatan? Adakah
0dibenarkan? - Adakah alamat link-local IPv6 dan zon seperti
%eth0mesti disokong? - Adakah rangkaian tersebut TCP, UDP atau soket Unix?
- Patutkah kurungan dan aksara kawalan dalam input pengguna ditolak?
- Bolehkah CI mengikat pendengar (listener) loopback IPv6?
Jawapan 30 saat
"Penggabungan ringkas tidak dapat menyatakan sempadan antara hos IPv6 dan portnya, jadi 2001:db8::1:443 adalah kabur. Saya mengesahkan port, kemudian memanggil net.JoinHostPort(host, strconv.Itoa(port)); pustaka standard mengeluarkan [host]:port untuk IPv6 dan mengekalkan zon. Saya tidak menambah kurungan secara manual. Jika autoriti lengkap diterima, saya menghuraikannya dengan net.SplitHostPort sebelum membina semula. Ujian meliputi IPv4, IPv6, %zone, DNS, input kosong, port tidak sah dan penghuraian pergi balik (round-trip). Penganalisis hostport go vet Go 1.25 ialah pintu statik, bukan pengganti kepada ujian rangkaian."
Penyelesaian terperinci
Langkah 1: Terangkan kegagalan tersebut
Alamat IPv4 mempunyai satu titik bertindih yang memisahkan hos dan port; alamat IPv6 mengandungi titik bertindih di dalamnya sendiri. Oleh itu, teks rangkaian IPv6 meletakkan hos dalam kurungan, seperti dalam [2001:db8::1]:443. Penggabungan ringkas tidak menyediakan sempadan, jadi penghurai tidak dapat mengetahui dengan pasti sama ada titik bertindih terakhir ialah pemisah port.
Langkah 2: Bina dengan pustaka standard
Tukarkan port kepada rentetan dan panggil net.JoinHostPort. Apabila hos mengandungi titik bertindih, ia menambah kurungan; nama DNS dan IPv4 kekal dalam bentuk biasa. Ia juga mengekalkan pengecam zon, jadi jangan tambah kurungan atau lepaskan (escape) teks sebelum memanggilnya.
func dialAddress(host string, port int) (string, error) {
if port < 1 || port > 65535 {
return "", fmt.Errorf("port out of range: %d", port)
}
return net.JoinHostPort(host, strconv.Itoa(port)), nil
}Langkah 3: Tentukan bentuk input
API harus menerima hos kosong, bukan autoriti yang sudah mengandungi port. Jika alamat lengkap mesti disokong, panggil net.SplitHostPort terlebih dahulu, normalkan bahagian-bahagian tersebut dan bina semula dengan JoinHostPort. Penggantian rentetan adalah tidak selamat untuk IPv6 dan zon.
Langkah 4: Kendalikan pengecam zon
Alamat link-local IPv6 mungkin berbentuk fe80::1%eth0, menghasilkan [fe80::1%eth0]:443. Zon membawa skop antara muka dan tidak boleh digugurkan. Sahkan aksara yang dibenarkan dan panjangnya supaya aksara kawalan atau teks autoriti yang tidak dijangka tidak dapat memasuki log atau konfigurasi hiliran.
Langkah 5: Sahkan dan huraikan alamat lengkap
Selepas pembinaan, panggil net.SplitHostPort untuk menyemak kebolehbalikan dan menegaskan bahawa hos dan port sepadan dengan input. Ia memerlukan alamat rangkaian yang mempunyai port; port yang hilang, titik bertindih tambahan dan kurungan yang tidak sepadan harus mengembalikan ralat yang boleh diambil tindakan.
Langkah 6: Fahami go vet hostport
Go 1.25 menambah penganalisis hostport, yang membenderakan corak fmt.Sprintf("%s:%d", host, port) yang digunakan untuk membina alamat bagi net.Dial. Ia menangkap kesilapan biasa, tetapi ia tidak boleh menggantikan kontrak konfigurasi, pengesahan zon, batas port atau ujian timbunan rangkaian sebenar.
Langkah 7: Bina matriks ujian
Liputi 127.0.0.1:443, [2001:db8::1]:443, [fe80::1%eth0]:443, nama DNS, hos kosong, port 0, 65536, nilai negatif dan input yang sudah diletakkan dalam kurungan. Di mana disokong, sambungkan ke pendengar loopback IPv4 dan IPv6; jika tidak, kekalkan ujian pembinaan dan pemisahan tulen serta dokumentasikan keupayaan CI.
Contoh jawapan berkualiti tinggi
"Kecacatan tersebut adalah sintaks alamat, bukan Dial: hos IPv6 mengandungi titik bertindih, jadi penggabungan ringkas tidak dapat mengehadkan port. Saya mentakrifkan API sebagai hos kosong ditambah port integer, menyemak 1..65535 dan memanggil net.JoinHostPort(host, strconv.Itoa(port)); saya tidak pernah menulis kurungan secara manual. Jika autoriti lengkap diterima, saya memisahkannya terlebih dahulu dan membina semula daripada hos dan port yang telah dinormalkan. Saya mengekalkan dan mengesahkan %eth0 untuk alamat link-local. Ujian meliputi IPv4, IPv6, zon, DNS, port tidak sah dan penghuraian boleh balik. go vet hostport Go 1.25 ialah pintu statik, manakala sambungan loopback IPv4/IPv6 menyediakan liputan integrasi."
Kesilapan biasa
- Terus menggunakan
fmt.Sprintf("%s:%d", ...)→ Sempadan hos dan port IPv6 menjadi kabur → gunakannet.JoinHostPort. - Menambah kurungan pada setiap hos secara manual → Format IPv4 dan DNS menjadi salah → biarkan pustaka standard memutuskan.
- Menggugurkan
%zone→ IPv6 link-local mungkin tidak dapat dihalakan → kekalkan dan sahkan zon. - Menganggap autoriti lengkap sebagai hos kosong → Port atau kurungan diduplikasi → takrifkan kontrak input dan pisahkan apabila diperlukan.
- Menguji IPv4 sahaja → Laluan kegagalan pengeluaran kekal tidak diliputi → sertakan IPv6, zon dan ujian loopback.
- Bergantung pada go vet sahaja → Input tersuai dan kegagalan masa jalan kekal → gabungkan ujian unit, pemisahan dan sambungan.
- Melangkau pengesahan port → Nilai negatif atau limpahan memasuki konfigurasi → semak julat sebelum pembinaan.
- Mencatat log alamat mentah yang tidak disahkan → Aksara kawalan atau konfigurasi sensitif mungkin bocor → normalkan dan catat log medan berstruktur.
Soalan susulan
Soalan susulan 1: Adakah JoinHostPort mengesahkan bahawa hos ialah IP yang sah?
Ia menggabungkan hos dan port mengikut sintaks alamat rangkaian; ia bukan resolusi DNS atau pengesahan perniagaan penuh. Sama ada domain, zon atau aksara khas dibenarkan bergantung pada kontrak input dan laluan penyelesai (resolver).
Soalan susulan 2: Mengapa tidak menggunakan titik bertindih terakhir sahaja?
Pemampatan IPv6, zon dan port yang hilang menjadikan peraturan rentetan rapuh. Pasangan standard Join/Split mengikut sintaks alamat dan melaporkan ralat kurungan atau port secara eksplisit.
Soalan susulan 3: Bolehkah rentetan port dihantar secara langsung?
Ya, JoinHostPort menerima port rentetan. Apabila input perniagaan adalah integer, sahkan julatnya dan tukarkan dengan strconv.Itoa supaya nilai negatif atau limpahan tidak diformatkan ke dalam alamat.
Soalan susulan 4: Bagaimanakah zon patut disanitasikan?
Kekalkan semantik zon yang diperlukan oleh antara muka, tetapi hadkan set aksara dan panjangnya. Jangan lakukan pengekodan berganda pada %; catat hos dan zon sebagai medan berstruktur yang berasingan jika boleh.
Soalan susulan 5: Bilakah url.URL patut digunakan sebaliknya?
Gunakan url.URL apabila membina URI HTTP atau HTTPS dengan skema, autoriti dan laluan. Gunakan JoinHostPort untuk host:port yang dihantar kepada net.Dial; jangan gabungkan URI secara manual.
Soalan susulan 6: Bagaimanakah anda membuktikan pembetulan tersebut berfungsi dengan IPv6 sebenar?
Dalam CI yang menyokong IPv6 atau persekitaran khusus, ikat pendengar [::1]:0, baca port yang diberikan dan sambungkan melalui pembina yang sama. Kekalkan ujian fungsi tulen untuk persekitaran tanpa IPv6 dan laporkan perbezaannya.