Untuk menguji goroutine bersamaan, saya menambahkan satu baris ke fungsi untuk membuatnya butuh waktu acak untuk kembali (hingga satu detik)
time.Sleep(rand.Int31n(1000) * time.Millisecond)
Namun ketika saya kompilasi, saya mendapatkan kesalahan ini
. \ crawler.go: 49: operasi tidak valid: rand.Int31n (1000) * time.Millisecond (tipe tidak cocok int32 dan waktu. Durasi)
Ada ide? Bagaimana saya bisa mengalikan durasi?
rand.Seed(time.Now().Unix())
time.Sleep(time.Second * 2)
Duration
*Duration
=Duration
, alih-alih yang asli yang sebenarnya lebih masuk akal:Duration
*int
=Duration
.int64(...) * Duration
jauh lebih masuk akal daripada castingDuration
, yang hanya merupakan pelanggaran mendasar tentang bagaimana unit harus bekerja. Sayangnya itu tidak berhasil. Anda benar-benar harus melakukanDuration * Duration
yang mengerikan.Anda harus melemparkannya ke format yang benar Playground.
Jika Anda akan memeriksa dokumentasi untuk tidur , Anda melihat bahwa itu memerlukan
func Sleep(d Duration)
durasi sebagai parameter. Rand.Int31n Anda kembaliint32
.Baris dari contoh berfungsi (
time.Sleep(100 * time.Millisecond)
) karena kompiler cukup pintar untuk memahami bahwa di sini konstanta 100 Anda berarti durasi. Tetapi jika Anda melewati variabel, Anda harus melemparkannya.sumber
Di Go, Anda bisa mengalikan variabel dari tipe yang sama, jadi Anda harus memiliki kedua bagian ekspresi dengan tipe yang sama.
Hal paling sederhana yang dapat Anda lakukan adalah melempar integer ke durasi sebelum mengalikan, tetapi itu akan melanggar semantik unit. Apa yang akan menjadi kelipatan durasi dengan durasi dalam satuan?
Saya lebih suka mengonversi waktu. Milidetik ke int64, dan kemudian mengalikannya dengan jumlah milidetik, lalu dilemparkan ke waktu. Durasi:
Dengan cara ini setiap bagian dari ekspresi dapat dikatakan memiliki nilai yang bermakna sesuai dengan tipenya.
int64(time.Millisecond)
bagian hanya nilai tanpa dimensi - jumlah unit terkecil dari nilai aslinya.Jika berjalan di jalur yang sedikit lebih sederhana:
Bagian kiri dari perkalian adalah omong kosong - nilai dari jenis "waktu. Durasi", memegang sesuatu yang tidak relevan dengan jenisnya:
Dan itu bukan hanya semantik, ada fungsi aktual yang terkait dengan jenis. Kode ini mencetak:
Menariknya, contoh kode di sini menggunakan kode paling sederhana, dengan semantik menyesatkan yang sama dari konversi Durasi: https://golang.org/pkg/time/#Duration
sumber
Sangat menyenangkan bahwa Go memiliki
Duration
tipe - memiliki unit yang didefinisikan secara eksplisit dapat mencegah masalah dunia nyata.Dan karena aturan tipe Go yang ketat, Anda tidak bisa mengalikan Durasi dengan bilangan bulat - Anda harus menggunakan gips untuk mengalikan tipe umum.
The dokumentasi resmi menunjukkan menggunakan metode # 1:
Tapi, tentu saja, mengalikan durasi dengan durasi seharusnya tidak menghasilkan durasi - itu tidak masuk akal di wajah itu. Contoh kasus, 5 milidetik kali 5 milidetik menghasilkan
6h56m40s
. Mencoba persegi 5 detik menghasilkan limpahan (dan bahkan tidak akan dikompilasi jika dilakukan dengan konstanta)Omong-omong,
int64
representasiDuration
dalam nanodetik "membatasi durasi terwakili terbesar hingga sekitar 290 tahun" , dan ini menunjukkan bahwaDuration
, sepertiint64
, diperlakukan sebagai nilai yang ditandatangani:,(1<<(64-1))/(1e9*60*60*24*365.25) ~= 292
dan itulah cara penerapannya:Jadi, karena kita tahu bahwa representasi yang mendasarinya
Duration
adalahint64
, melakukan pemeran di antaraint64
danDuration
merupakan NO-OP yang masuk akal - hanya diperlukan untuk memenuhi aturan bahasa tentang jenis pencampuran, dan itu tidak berpengaruh pada operasi penggandaan selanjutnya.Jika Anda tidak suka casting karena alasan kemurnian, kubur dalam panggilan fungsi seperti yang saya tunjukkan di atas.
sumber
Untuk penggandaan variabel ke waktu. Kedua menggunakan kode berikut
sumber
time.Duration
variabel Go . Anda menyebutkan variabeladdOneHrDuration
waktu Anda,time.Duration
tetapi kemudian lanjutkan untuk mengaturnya menjadi 3600 ns bukan satu jam. Atime.Duration
kebetulan memiliki unit dasar nanodetik. Untuk benar-benar mendapatkan durasi satu jam Anda bisa melakukan sesuatu seperti:const oneHourDuration = 60 * time.Hour
(atau3600 * time.Second
atautime.Hour
).