Süre tamsayı ile nasıl çarpılır?


286

Eşzamanlı goroutinleri test etmek için, bir işleve bir dönüş ekledim (dönüş bir saniye kadar)

time.Sleep(rand.Int31n(1000) * time.Millisecond)

Ancak derlediğimde bu hatayı aldım

. \ crawler.go: 49: geçersiz işlem: rand.Int31n (1000) * time.Millisecond (uyumsuz tip int32 ve time.Duration).

Herhangi bir fikir? Süreyi nasıl çarpabilirim?

Yanıtlar:


432

int32ve time.Durationfarklı türlerdir. Sen dönüştürmek için gereken int32bir etmek time.Durationgibi time.Sleep(time.Duration(rand.Int31n(1000)) * time.Millisecond).


5
Teşekkürler işe yaradı. Ayrıca rastgele sayı üretecini tohumlamayı öğrendimrand.Seed(time.Now().Unix())
Albay Panic

44
sadece bilgim için, aşağıdakiler nasıl çalışır? time.Sleep(time.Second * 2)
İşhan Khare

60
Çalışır, çünkü sabitler nasıl kullanıldıklarına bağlı olarak uyarlanabilir bir türe sahiptir. Bu ayrıntılı olarak açıklıyor Rob Pike tarafından blog yazısı bakın blog.golang.org/constants
MNA

28
Bunun nedeninin basit tip sistemine seferde o tuhaf şeylerden biridir (bu durumda aşırı operatörün eksikliği) - Eğer çarpma döküm zorunda Duration* Duration= Durationyerine aslında daha mantıklı orijinal birinin,: Duration* int= Duration.
Timmmm

14
Operatörün aşırı yüklenmesi veya örtük sayısal dönüşüm bu çalışmayı sağlar. Bence örtük sayısal dönüşümleri dışarıda bırakma hakkı vardı. int64(...) * DurationDökümden çok daha mantıklı olan bu konuya baktıktan sonra Duration, birimlerin nasıl çalışması gerektiğinin temel bir ihlalidir. Ne yazık ki bu işe yaramıyor. Gerçekten Duration * Durationkorkunç olanı yapmak zorundasın .
Timmmm

61

Doğru biçime dökmeniz gerekir Playground.

yourTime := rand.Int31n(1000)
time.Sleep(time.Duration(yourTime) * time.Millisecond)

Uyku belgelerini kontrol ederseniz , func Sleep(d Duration)parametre olarak süre gerektirdiğini görürsünüz . Kişisel rand.Int31n döner int32.

Örnek time.Sleep(100 * time.Millisecond)derleme çalışır ( ) çünkü derleyici burada 100 sabitinizin bir süre anlamına geldiğini anlayacak kadar akıllıdır . Ancak bir değişkeni iletirseniz, değişkeni atmalısınız.


16

Git'te, aynı türdeki değişkenleri çarpabilirsiniz, bu nedenle ifadenin her iki bölümünün de aynı tür olması gerekir.

Yapabileceğiniz en basit şey, çarpmadan önce süreye bir tam sayı atamaktır, ancak bu birim semantiğini ihlal eder. Birimler cinsinden sürenin süreye göre çarpımı ne olur?

Zaman dönüştürmeyi tercih ederim. Milisaniyeyi bir int64'e çevirip milisaniye ile çarpın, sonra zamana ayarlayın.

time.Duration(int64(time.Millisecond) * int64(rand.Int31n(1000)))

Bu şekilde, ifadenin herhangi bir bölümünün türüne göre anlamlı bir değere sahip olduğu söylenebilir. int64(time.Millisecond)bölüm yalnızca boyutsuz bir değerdir - orijinal değerdeki en küçük zaman birimi sayısı.

Biraz daha basit bir yol yürürseniz:

time.Duration(rand.Int31n(1000)) * time.Millisecond

Çarpmanın sol kısmı saçmalıktır - türüyle alakasız bir şey tutan "time.Duration" türünün bir değeri:

numberOfMilliseconds := 100
// just can't come up with a name for following:
someLHS := time.Duration(numberOfMilliseconds)
fmt.Println(someLHS)
fmt.Println(someLHS*time.Millisecond)

Ve sadece semantik değil, türlerle ilişkili gerçek işlevsellik de var. Bu kod yazdırılır:

100ns
100ms

İlginç bir şekilde, buradaki kod örneği, Süre dönüşümünün aynı yanıltıcı anlamıyla en basit kodu kullanır: https://golang.org/pkg/time/#Duration

saniye: = 10

fmt.Print (time.Duration (saniye) * time.Second) // 10 saniye yazdırır


5

Go'nun bir Durationtürü olması güzeldir - açıkça tanımlanmış birimlere sahip olmak gerçek dünya sorunlarını önleyebilir.

Ve Go sıkı tip kuralları, çünkü olamaz çarpın bir tamsayı tarafından Süresi - Eğer gerekir çarpma yaygın türleri için bir döküm kullanın.

/*
MultiplyDuration Hide semantically invalid duration math behind a function
*/
func MultiplyDuration(factor int64, d time.Duration) time.Duration {
    return time.Duration(factor) * d        // method 1 -- multiply in 'Duration'
 // return time.Duration(factor * int64(d)) // method 2 -- multiply in 'int64'
}

Resmi belgeler yöntemi 1. kullanılarak gösterir:

Tam sayı bir birimi bir Süreye dönüştürmek için çarpın:

seconds := 10
fmt.Print(time.Duration(seconds)*time.Second) // prints 10s

Ancak, elbette, bir süreyi bir süreyle çarpmak bir süre üretmemelidir - bu, yüzünde saçmadır. Durumda, 5 milisaniye çarpı 5 milisaniye üretir 6h56m40s. 5 saniye kare denemeye çalışmak taşmaya neden olur (ve sabitlerle yapılırsa bile derlenmez).

Bu arada, int64temsili Durationnanosaniye "Yaklaşık 290 yıl gösterilebilir en büyük süresini sınırlar" ve bu belirtir Duration, böyle int64imzalı bir değer olarak ele alınır: (1<<(64-1))/(1e9*60*60*24*365.25) ~= 292ve bu böyle uygulanır aynen böyle:

// A Duration represents the elapsed time between two instants
// as an int64 nanosecond count. The representation limits the
// largest representable duration to approximately 290 years.
type Duration int64

Bu nedenle, bunun temel temsilinin Durationan olduğunu int64, aradaki dökümün gerçekleştirilmesi int64ve Durationmantıklı bir NO-OP olduğunu biliyoruz - sadece karıştırma türleri ile ilgili dil kurallarını karşılamak için gerekli ve sonraki çarpma işlemi üzerinde hiçbir etkisi yoktur.

Saflık nedeniyle dökümden hoşlanmıyorsanız, yukarıda gösterdiğim gibi bir işlev çağrısına gömün.


msgstr " ortak türlerle / ile çarp".
nobar

Bölme ile ilgili benzer tartışma burada (yanlış) cevabında .
nobar

-3

Değişkenin zamana çarpımı için.

    oneHr:=3600
    addOneHrDuration :=time.Duration(oneHr)
    addOneHrCurrTime := time.Now().Add(addOneHrDuration*time.Second)

Bu, Go time.Durationdeğişkenlerini kullanmanın iyi bir yolu değildir . addOneHrDurationZaman değişkeninizi adlandırın , time.Durationancak daha sonra bir saate değil 3600 ns olarak ayarlamaya devam edin. A'nın time.Durationnanosaniye baz birimleri vardır. Aslında bir saatlik bir süre almak için: const oneHourDuration = 60 * time.Hour(veya 3600 * time.Secondveya time.Hour) gibi bir şey yapabilirsiniz .
Dave C
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.