Saya sedang mengembangkan klien API di mana saya harus menyandikan muatan JSON berdasarkan permintaan dan mendekode badan JSON dari respons.
Saya telah membaca kode sumber dari beberapa perpustakaan dan dari apa yang telah saya lihat, pada dasarnya saya memiliki dua kemungkinan untuk menyandikan dan mendekode string JSON.
Gunakan json.Unmarshal
meneruskan seluruh string respons
data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
err = json.Unmarshal(data, value)
}
atau menggunakan json.NewDecoder.Decode
err = json.NewDecoder(resp.Body).Decode(value)
Dalam kasus saya, ketika berhadapan dengan respons HTTP yang mengimplementasikan io.Reader
, versi kedua tampaknya memerlukan lebih sedikit kode, tetapi karena saya telah melihat keduanya, saya bertanya-tanya apakah ada preferensi apakah saya harus menggunakan solusi daripada yang lain.
Selain itu, jawaban yang diterima dari pertanyaan ini mengatakan
Silakan gunakan
json.Decoder
sebagai gantijson.Unmarshal
.
tapi itu tidak menyebutkan alasannya. Haruskah saya benar-benar menghindari menggunakan json.Unmarshal
?
ioutil.ReadAll
adalah hampir selalu hal yang salah untuk dilakukan. Ini tidak terkait dengan tujuan Anda, tetapi mengharuskan Anda untuk memiliki cukup memori yang berdekatan untuk menyimpan apa pun yang mungkin terjadi, bahkan jika 20TB respons terakhir adalah setelah yang terakhir}
di JSON Anda.io.LimitReader
untuk mencegahnya.Jawaban:
Itu benar-benar tergantung pada apa input Anda. Jika Anda melihat implementasi
Decode
metodejson.Decoder
, itu buffer seluruh nilai JSON dalam memori sebelum mengosongkannya menjadi nilai Go. Jadi, dalam kebanyakan kasus, ini tidak akan lebih hemat memori (meskipun ini dapat dengan mudah berubah dalam versi bahasa yang akan datang).Jadi aturan praktis yang lebih baik adalah ini:
json.Decoder
jika data Anda berasal dariio.Reader
aliran, atau Anda perlu mendekodekan beberapa nilai dari aliran data.json.Unmarshal
jika Anda sudah memiliki data JSON dalam memori.Untuk kasus membaca dari permintaan HTTP, saya akan memilih
json.Decoder
karena Anda jelas membaca dari aliran.sumber
Buffered
Metode yang ada untuk membiarkan Anda melihat data tambahan yang dibacakan ke dalam buffer internal setelah nilai.