Tek programda temeller
time.Now() mevcut yerel zamanı döndürür, time.Sleep mevcut goroutine'i duraklatır, time.Since geçen süreyi ölçer, time.Date ise belirli bir anı oluşturur. Bu sayfanın geri kalanı her parçayı sırayla ele alıyor. Örnekler, çıktıları nerede çalıştırırsanız çalıştırın aynı olsun diye sabit tarihler ve UTC kullanır.
Sleep ve Duration
Bir time.Duration, nanosaniye sayan bir int64'tür. Paket okunabilir değerler oluşturmak için sabitler tanımlar:
| Sabit | Değer |
|---|---|
time.Nanosecond | 1 |
time.Microsecond | 1000 ns |
time.Millisecond | 1000 µs |
time.Second | 1000 ms |
time.Minute | 60 s |
time.Hour | 60 dk |
time.Day yoktur, çünkü bir saat dilimi yaz saati için değiştiğinde bir gün her zaman 24 saat değildir. Takvim günleri için AddDate kullanın (aşağıya bakın).
İki yaygın hata Duration'ın bir tam sayı olmasından gelir:
time.Sleep(5)5 nanosaniye bekler. Her zaman bir birimle çarpın:time.Sleep(5 * time.Second).nbirintdeğişkeni olduğundatime.Sleep(n * time.Second)derlenmez. Dönüştürün:time.Duration(n) * time.Second.5gibi bir sabit dönüşüm olmadan çalışır, çünkü tipsiz sabitler Duration tipine uyum sağlar.
ParseDuration; ns, us (ya da µs), ms, s, m ve h birimlerini "2h45m" ya da "1.5s" gibi birleşik olarak kabul eder. Gün için birimi yoktur.
Biçimlendirme: 2006-01-02 referans düzeni
Go, %Y-%m-%d ya da yyyy-MM-dd kullanmaz. Bir düzen, referans zamanının
Mon Jan 2 15:04:05 MST 2006
çıktınızın görünmesini istediğiniz şekilde yazılmış halidir. Değerler her biri benzersiz olacak şekilde seçilmiştir: ay 1, gün 2, saat 3 (ya da 15), dakika 4, saniye 5, yıl 6 (2006), dilim farkı -7 (-0700). Onu 01/02 03:04:05PM '06 -0700 olarak okuyun.
En çok ihtiyaç duyacağınız düzen token'ları:
| Token | Anlamı | Örnek |
|---|---|---|
2006 / 06 | yıl, 4 ya da 2 basamak | 2026 / 26 |
01 / 1 / Jan / January | ay | 03 / 3 / Mar / March |
02 / 2 / _2 | ayın günü (sıfırla dolgulu, düz, boşlukla dolgulu) | 05 / 5 / " 5" |
Mon / Monday | haftanın günü | Thu / Thursday |
15 | saat, 24 saatlik | 09 |
03 / 3 | saat, 12 saatlik | 09 / 9 |
04 / 4 | dakika | 07 / 7 |
05 / 5 | saniye | 03 / 3 |
PM / pm | AM ya da PM işareti | AM |
.000 / .999 | saniye kesirleri (sabit / sondaki sıfırlar kırpılmış) | .250 / .25 |
MST | dilim kısaltması | UTC |
-0700 / -07:00 | sayısal dilim farkı | +0000 / +00:00 |
Z07:00 | -07:00 gibi, ama UTC için Z yazar | Z |
Önceden tanımlı düzenler:
| Sabit | Düzen |
|---|---|
time.RFC3339 | 2006-01-02T15:04:05Z07:00 (API'ler ve JSON için bunu kullanın) |
time.RFC3339Nano | 2006-01-02T15:04:05.999999999Z07:00 |
time.DateTime (Go 1.20) | 2006-01-02 15:04:05 |
time.DateOnly (Go 1.20) | 2006-01-02 |
time.TimeOnly (Go 1.20) | 15:04:05 |
time.Kitchen | 3:04PM |
time.RFC1123 | Mon, 02 Jan 2006 15:04:05 MST (HTTP tarihleri bunun yerine http.TimeFormat kullanır) |
Klasik hata, bir düzeni yanlış sayılarla yazmaktır, örneğin "2023-01-01". Go bunu reddetmez. Tanımadığı karakterleri kopyalar, tanıdıklarını ise yerine koyar: her 2 gündür, 3 12 saatlik saattir ve iki 01 de aydır, bu yüzden 5 Mart saat 9:07 5059-03-03 olarak biçimlendirilir. "YYYY-MM-DD" gibi bir düzen hiç token içermez ve kendini değiştirmeden yazdırır. Biçimlendirilmiş tarihler tuhaf görünüyorsa düzenin tam olarak referans değerlerini kullandığını kontrol edin.
String'leri zamana ayrıştırmak
time.Parse(layout, value) aynı düzenleri kullanır ve kontrol etmeniz gereken bir hata döndürür:
Girdide dilim yoksa Parse UTC döndürür. Aynı duvar saati string'i dilime göre farklı anlar ifade edebilir; ParseInLocation'ın var olmasının nedeni budur. Hata mesajı eşleşmeyen kısmı adlandırır; bu da bir düzende hata ayıklarken yardımcı olur.
Saat dilimleri
Bir time.Time, bir an artı gösterim için kullanılan bir konumdur. Konumu In ile değiştirmek hangi an olduğunu değil, nasıl yazdırıldığını değiştirir.
time.UTCher zaman kullanılabilir. Zamanları UTC olarak (ya da bir farkla RFC 3339 olarak) saklayın ve iletin, yalnızca gösterim için dönüştürün.time.Localmakinenin dilimidir. Sunucularda ve container'larda çoğu zaman UTC'dir, dizüstü bilgisayarda değildir; bu yüzden ona bağlı kod her yerde farklı davranır.time.LoadLocation("Europe/Berlin")IANA veritabanını işletim sisteminden okur. Minimal container imajlarında çoğu zaman yoktur ve çağrı o zaman bir hata döndürür. Boş import_ "time/tzdata"veritabanını binary'nize gömer (yaklaşık 450 KB), böylece her zaman çalışır. Hatayı her zaman ele alın.time.FixedZone(name, offsetSeconds)sabit farklı bir dilim oluşturur. Yaz saati kuralları yoktur, bu yüzden onu adlandırılmış bölgeler için değil, aldığınız farklar için kullanın.
Aritmetik ve karşılaştırma
Çıktıda dikkat edilecekler:
- 31 Ocak'ta
AddDate(0, 1, 0), 28 Şubat değil 3 Mart verir. Go bir ay ekleyerek "31 Şubat"ı elde eder ve sonra taşmayı normalleştirir. "Gelecek ay aynı gün, sınırlandırılmış" istiyorsanız o mantığı kendiniz yazın. SubbirDurationdöndürür ve bu yaklaşık 292 yılda tavan yapar. Takvim günü farkları için tarihleri UTC gece yarısında karşılaştırın ve 24 saate bölün.- Günün başlangıcını almak için zamanı
Date()'ten yeniden oluşturun.t.Truncate(24 * time.Hour)UTC'deki sıfır zamana göre yuvarlar, bu yüzden UTC dışındaki her dilim için yanlış cevap verir.
== ile değil, Equal, Before, After ile karşılaştırın. time.Now() bir monotonik saat okuması içerir; bu, duvar saati ayarlansa bile time.Since'in doğru kalması için kullanılır. == bu okumayı ve konumu da karşılaştırır, bu yüzden aynı ana ait iki Time değeri eşit olmayabilir. Aynı nedenle, önce normalleştirmeden time.Time'ı map anahtarı olarak kullanmayın (t.UTC().Round(0) monotonik okumayı kaldırır).
Sıfır değerli time.Time, 1. yılın 1 Ocak'ı, 00:00 UTC'dir. Onu t.IsZero() ile kontrol edin.
Geçen süreyi ölçmek
start := time.Now()
doWork()
log.Printf("doWork took %v", time.Since(start))
time.Since(start), time.Now().Sub(start)'tır; time.Until(deadline) ise deadline.Sub(time.Now())'dır. İkisi de mümkün olduğunda monotonik saati kullanır, bu yüzden sistem saati değişikliklerine karşı güvenlidir. Kod benchmark'ı için elle zamanlamak yerine testing paketindeki Go'nun benchmark desteğini kullanın.
Timer'lar ve ticker'lar
time.After(d), d'den sonra bir kez değer alan bir channel döndürür. Bir time.Timer, Stop metodu olan aynı şeydir. Bir time.Ticker siz durdurana kadar her periyotta bir değer iletir.
20, 40 ve 60 ms'deki üç tick 110 ms'lik timer'dan çok önce gelir, bu yüzden program üçüncü tick'ten sonra durur. time.AfterFunc(d, f), f'yi d'den sonra kendi goroutine'inde çalıştırır; bu da tek seferlik gecikmeli işler için kullanışlıdır.
Go 1.23'ten beri artık başvurulmayan timer'lar ve ticker'lar, Stop hiç çağrılmasa bile çöp toplayıcı tarafından toplanır ve durdurulmuş ya da sıfırlanmış bir timer'ın channel'ı artık eski bir değer iletmez. Stop'u defer ile çağırmak yine de ticker'ın ömrünün bittiğini söylemenin açık yoludur. Bir zaman sınırı tek bir beklemeye değil bütün bir işleme uygulanıyorsa bir context.WithTimeout genellikle bir timer'dan daha iyi okunur.
JSON'da zaman
time.Time, JSON'da nanosaniye hassasiyetle RFC 3339 string'lerine otomatik olarak dönüşür ve onlardan geri okunur:
type Event struct {
Name string `json:"name"`
At time.Time `json:"at"`
}
// {"name":"deploy","at":"2026-09-23T14:30:00Z"}
Farklı bir biçimdeki JSON string'i çözülemez. Unix zaman damgaları ya da özel biçimler için bir int64 ya da string saklayıp dönüştürün veya kendi UnmarshalJSON'u olan bir tip tanımlayın.
Sık yapılan hatalar
- Düz bir sayıyla
time.Sleep(1)ya datime.Sleep(n). Bu nanosaniyedir. - Yanlış rakamlı düzenler.
"2023-01-01"ya da"YYYY-MM-DD"düzen değildir."2006-01-02"kullanın. - Dakika ile ayı karıştırmak. Dakikalar
04, aylar01'dir."15:01"dakikayı değil, saati ve ardından ayı yazdırır. ==ile karşılaştırmak.Equalkullanın.time.Local'a güvenmek. Makineler arasında farklıdır.time.UTCya da yüklenmiş bir konumla açık olun.LoadLocationya daParse'tan gelen hatayı yok saymak. İkisi de gerçek girdide başarısız olur. Başarısız birParse, 1. yıl olarak yazdırılan sıfır zamanı döndürür; başarısız birLoadLocationiset.In(loc)'u panic'e sokannilbir konum döndürür.
Sıkça Sorulan Sorular
Go'da nasıl beklenir (sleep)?
time.Sleep'i bir time.Duration ile çağırın: time.Sleep(2 * time.Second) ya da time.Sleep(500 * time.Millisecond). time.Sleep(2) gibi düz bir sayı derlenir ama 2 nanosaniye bekler, çünkü bir Duration nanosaniye sayar. Sleep yalnızca mevcut goroutine'i bloklar.
Go tarih formatları için neden 2006-01-02 15:04:05 kullanıyor?
Go tarihleri örnekle biçimlendirir. Düzen, çıktınızın görünmesini istediğiniz şekilde yazılmış Mon Jan 2 15:04:05 MST 2006 referans zamanıdır. Parçaları Amerikan sırasıyla artarak sayar: ay 1, gün 2, saat 3 (24 saatlik saatte 15), dakika 4, saniye 5, yıl 6 (2006), dilim farkı 7 (-0700). Yani "2006-01-02" yıl-ay-gün, "02/01/2006" ise gün/ay/yıl demektir.
Go'da bir tarih string'i nasıl ayrıştırılır?
Referans zamanıyla yazılmış bir düzenle time.Parse(layout, value) kullanın: t, err := time.Parse("2006-01-02", "2026-09-23"). err'i her zaman kontrol edin. String'de dilim bilgisi yoksa sonuç UTC'dir; onu başka bir dilimde yorumlamak için time.ParseInLocation kullanın.
Go'da Unix zaman damgası nasıl alınır?
time.Now().Unix(), 1 Ocak 1970 UTC'den bu yana geçen saniyeleri bir int64 olarak döndürür. UnixMilli(), UnixMicro() ve UnixNano() daha ince birimler verir. Tersi için time.Unix(sec, 0) ya da time.UnixMilli(ms) kullanın.
Go'da iki zaman nasıl karşılaştırılır?
t1.Before(t2), t1.After(t2) ve t1.Equal(t2) kullanın. == kullanmayın: konumu ve monotonik saat okumasını da karşılaştırır, bu yüzden aynı ana ait iki değer eşit olmayabilir. t2.Sub(t1) farkı bir Duration olarak verir.