Topik wawancara representatif

Wawancara coding: Bagaimana cara menjaga urutan pemeriksaan error Go setelah Go 1.25 memperbaiki pemeriksaan nil yang tertunda?

CodingSulit
Tim Redaksi Offer.ccDipublikasikan Diperbarui

Pertanyaan

Go 1.25 memperbaiki bug kompilator yang dapat menunda pemeriksaan nil-pointer. Jelaskan mengapa penanganan error di bawah ini tidak aman, bagaimana Anda akan menulis ulang kodenya, bagaimana Anda akan menguji peningkatan versi, dan mengapa perilaku kompilator lama bukanlah sebuah kontrak.

Konsep dan waktu penerapannya

Sebuah layanan menerima pointer dan error dari API file atau jaringan. Kompilator versi lama dapat menunda pemeriksaan nil di sekitar akses anggota, sehingga jalur error tidak selalu gagal secara langsung. Setelah meningkatkan versi ke Go 1.25, kode yang sama mengekspos masalah tersebut sesuai dengan semantik bahasa. Jelaskan urutan pemeriksaan yang benar, batasan dereferensi implisit, strategi migrasi, dan verifikasi.

Ini cocok untuk peran backend Go, infrastruktur, dan kakas kompilator. Pertanyaan ini menguji apakah Anda menghubungkan spesifikasi bahasa, konvensi penanganan error, dan risiko peningkatan versi. Go 1.25 mencatat perbaikan ini; spesifikasi Go menyatakan bahwa mengevaluasi selektor field melalui pointer nil akan memicu panic; panduan kompatibilitas Go memperingatkan bahwa kode yang bergantung pada bug kompilator dapat rusak ketika bug tersebut diperbaiki.

Nama file, kombinasi hasil, jumlah pengujian, dan rentang versi di bawah ini adalah placeholder. Ganti dengan fakta dari proyek yang dapat Anda pertahankan.

Apa yang sedang diuji oleh pewawancara

Pertama, apakah Anda memeriksa operasi yang menghasilkan error sebelum menggunakan hasil yang kemungkinan bernilai nil?

Kedua, dapatkah Anda membedakan kode yang melanggar spesifikasi dari kompilator lama yang kebetulan tidak mengekspos error tersebut? Yang terakhir bukanlah perilaku kompatibilitas.

Ketiga, dapatkah Anda menjelaskan selektor field, dereferensi pointer, pemanggilan method, dan interface nil tanpa mencampuradukkan aturannya?

Keempat, dapatkah Anda merancang verifikasi peningkatan versi menggunakan pencarian statis, pengujian unit, pengujian integrasi, canary, dan metrik runtime secara bersamaan?

Kelima, dapatkah Anda menentukan cakupan dan rollback? Menurunkan versi (downgrade) kompilator tidak memperbaiki jalur error; hal itu hanya dapat menunda kegagalan.

Pertanyaan untuk diklarifikasi sebelum menjawab

  • Apa tipe pointer yang dikembalikan, dan bisakah error non-nil muncul bersamaan dengan nilai non-nil?
  • Apakah akses tersebut berupa field, method, atau panggilan interface? Perilaku nil berbeda untuk masing-masingnya.
  • Versi Go mana yang digunakan untuk mem-build program, dan apakah ada matriks versi?
  • Apakah perilaku lama diamati dalam pengujian atau produksi, atau hanya diasumsikan?
  • Apakah kegagalan harus mengembalikan error, melewati pekerjaan, atau panic? Kontrak API yang menentukannya.
  • Jalur mana yang paling mungkin dieksekusi setelah peningkatan versi? Urutkan berdasarkan tingkat error, lalu lintas data, dan tipe data.

Kerangka jawaban 30 detik

“Kode ini menggunakan hasil yang kemungkinan bernilai nil sebelum memeriksa error, sehingga jalur kegagalan menjadi tidak aman. Spesifikasi Go menetapkan bahwa evaluasi field pointer nil menghasilkan panic, dan Go 1.25 memperbaiki bug kompilator lama yang menunda pemeriksaan tersebut. Saya akan memeriksa error segera setelah pemanggilan fungsi, kemudian baru mengakses objek; menambahkan pengujian untuk kombinasi nil dan non-nil, akses field, dan pemanggilan method; serta menggunakan CI multi-versi ditambah metrik canary. Jika pengujian terdahulu bergantung pada perilaku lama, saya akan memperbaiki kode dan pengujiannya alih-alih menganggap penurunan versi kompilator sebagai perbaikan.”

Jawaban mendalam langkah demi langkah

Langkah 1: Memulihkan kontrak pengembalian nilai

Baca dokumentasi dan implementasi fungsi yang dipanggil. Pastikan apakah error non-nil mengizinkan penggunaan objek. Jika kontrak tidak jelas, perlakukan objek sebagai tidak dapat digunakan daripada bergantung pada asumsi “biasanya non-nil”.

Langkah 2: Tangani error sebelum melakukan dereferensi

Gunakan pola: panggil, segera periksa error, lalu baca field atau panggil method. Ini menyelaraskan alur kontrol dengan kontrak dan membuat peninjauan statis menjadi efektif.

go
f, err := os.Open(name)
if err != nil {
    return err
}
defer f.Close()
info, err := f.Stat()
if err != nil {
    return err
}
use(info.Name())

Jika suatu error sengaja membawa hasil parsial yang dapat digunakan, dokumentasikan aturan tersebut dalam API dan ekspos tipe hasil atau komentar yang eksplisit; jangan biarkan pemanggil menebak-nebak.

Langkah 3: Bedakan nil implisit dan eksplisit

Selektor field dapat mendereferensi pointer secara implisit, sedangkan dereferensi eksplisit juga memicu panic pada nil. Method dengan pointer-receiver, nilai dinamis nil dalam interface, dan interface nil memiliki aturan yang berbeda. Sebutkan ekspresinya sebelum menyatakan hasil runtime-nya.

Langkah 4: Menilai dampak peningkatan versi

Cari penggunaan objek sebelum pemeriksaan error, prioritaskan jalur file, jaringan, penguraian (parsing), database, dan cache. Build rangkaian pengujian yang sama dengan Go 1.24 dan 1.25, lalu catat panic baru, tingkat error, dan jalur permintaan. Kompilasi saja bukan merupakan verifikasi semantik.

Langkah 5: Rancang rilis yang dapat dibatalkan (reversible)

Perbaiki urutan pemeriksaan terlebih dahulu, lalu lakukan canary pada versi Go. Pantau panic, kode error, percobaan ulang (retry), latensi, dan kebocoran sumber daya. Jika versi baru mengekspos banyak cacat nyata, lakukan rollback pada image untuk membatasi dampak, namun tetap simpan perbaikan kode dan daftar cacat tersebut.

Langkah 6: Masukkan aturan ke dalam toolchain

Wajibkan aturan “periksa error segera setelah fungsi kembali” dalam peninjauan dan analisis statis. Tambahkan pengujian fault-injection untuk hasil nil, error non-nil, short read, dan kegagalan penutupan (close). Catat perilaku mana yang berasal dari spesifikasi dan mana yang hanya merupakan kebetulan dari implementasi lama.

Contoh jawaban berkualitas tinggi

Contoh ini adalah materi latihan fiktif.

go
f, err := os.Open("missing")
name := f.Name()
if err != nil {
    return err
}
fmt.Println(name)

“Kode tersebut mengakses f.Name() sebelum memeriksa error. Pembukaan yang gagal dapat mengembalikan objek file nil, sehingga akses field atau method menjadi tidak aman. Go 1.25 memperbaiki cacat kompilator yang menunda pemeriksaan nil ini pada beberapa versi lama; fakta bahwa kode lama tidak langsung gagal bukanlah sebuah jaminan. Bentuk yang benar memeriksa error terlebih dahulu, kemudian menggunakan f, dan melakukan defer f.Close() saat berhasil.

Saya akan memindai pemanggilan serupa, menggunakan fault injection untuk kombinasi error dan objek, serta menjalankan race detector, pengujian integrasi, dan CI multi-versi. Selama proses canary, saya akan mengorelasikan panic, error, percobaan ulang, dan latensi; jika batas terlampaui, lakukan rollback pada image runtime sambil tetap mempertahankan perbaikan kode. Terakhir, saya akan memasukkan aturan spesifikasi ke dalam pemeriksaan peninjauan sehingga perbaikan kompilator tidak disalahartikan sebagai perubahan perilaku bisnis.”

Kesalahan umum

  • Menggunakan hasil sebelum memeriksa error: memperlakukan suatu ketidaksengajaan sebagai kontrak.
  • Hanya mengatakan “Go 1.25 lebih ketat”: mengabaikan spesifikasi dan alur kontrol.
  • Melakukan recover pada panic untuk menyembunyikan bug: recovery tidak menggantikan jalur penanganan error yang benar.
  • Hanya menjalankan proses build: perubahan semantik memerlukan fault injection, metrik runtime, dan canary.
  • Melakukan downgrade secara terburu-buru: mengembalikan cacat dapat menunda terjadinya insiden.
  • Mencampuradukkan aturan nil pada field, method, dan interface: sebutkan ekspresi yang tepat.

Pertanyaan lanjutan dan jawaban

Bagaimana jika sebuah API mengembalikan nilai non-nil bersamaan dengan error non-nil?

Ikuti kontrak eksplisitnya. Jika tidak ada, kembalikan error dan jangan gunakan nilainya. Untuk keberhasilan parsial, tentukan tipe hasil yang eksplisit dan uji setiap statusnya.

Mengapa versi lama tidak langsung memicu panic?

Catatan rilis mengaitkannya dengan bug kompilator yang menunda pemeriksaan nil. Suatu program tidak dapat memperlakukan manifestasi bug sebagai jaminan bahasa.

Bagaimana Anda membuktikan bahwa perbaikan tersebut tidak memperluas pemadaman (outage)?

Jalankan pengujian fault-injection dan integrasi yang sama pada versi lama dan baru, kemudian lakukan canary sambil memantau panic, error, percobaan ulang, latensi, dan penutupan sumber daya.

Kapan panic dapat diterima?

Hanya ketika invarian tingkat proses dilanggar dan tidak ada kontrak yang dapat dipulihkan. Kegagalan I/O biasa, parsing, dan dependensi harus mengembalikan error yang terstruktur.

Bagaimana jika tim menginginkan perilaku lama?

Jelaskan bahwa perilaku tersebut tetap bergantung pada cacat implementasi. Perbaiki urutan pemanggilan, dokumentasikan risiko kompatibilitas, dan gunakan rollback hanya untuk penanganan jangka pendek.

Sumber publik

Pertanyaan terkait

Alat wawancara terkait

Gunakan Tangkapan Layar untuk perintah coding

Ambil tangkapan layar soal, lalu telusuri batasan, solusi, kode, edge case, dan kompleksitas secara berurutan.

Lihat alat