Menu

Golang Type Assertion: x.(T), Virgül-ok ve Type Switch

Bir type assertion, somut değeri bir interface'in içinden çıkarır. x.(T)'yi, asla panic yapmayan virgül-ok biçimini, başka bir interface'e assertion'ı, type switch'leri ve sarmalanmış hatalar için errors.As'i öğrenin.

Bu sayfada çalıştırılabilir editörler var - düzenle, çalıştır ve sonucu anında gör.

x.(T): değeri bir interface'ten çıkarmak

Bir interface değeri tuttuğu somut tipi gizler. Bir type assertion x.(T) onu geri ister.

Çıktı:

gopher 6
0 false
string of length 6

x'in bir interface tipi olmalıdır. Somut bir tip üzerinde assertion derlenmez: invalid operation: s (variable of type string) is not an interface.

Tek değerli biçim panic olur

Assertion yanlış olduğunda tek değerli biçim, iki tipi de adlandıran bir mesajla panic olur:

Çıktı:

recovered: interface conversion: interface {} is int, not string

Tek değerli biçimi yalnızca farklı bir tipin, çökmesini istediğiniz bir programlama hatası olacağı durumlarda kullanın. Diğer her yerde virgül-ok kullanın. Başarısızlıkta virgül-ok, T'nin sıfır değerini ve false verir.

Nil bir interface üzerinde assertion da başarısız olur: var v any; v.(string), interface conversion: interface {} is nil, not string ile panic olur, virgül-ok biçimi ise "", false döndürür.

Başka bir interface'e assertion

T bir interface tipi olabilir. Assertion bu durumda dinamik değer T'yi gerçekleştiriyorsa başarılı olur ve sonuç aynı dinamik değeri korur. Standart kütüphane isteğe bağlı yetenekleri böyle kontrol eder.

io.Copy, kaynağının io.WriterTo'yu gerçekleştirip gerçekleştirmediğini kontrol eder ve gerçekleştiriyorsa onu kullanır. fmt, Stringer ve error'u kontrol eder. Bu kalıp, küçük bir interface'in küçük kalmasını sağlarken çağıranların daha zengin gerçekleştirmelerden yararlanmasına da izin verir.

Type switch

Bir değer birkaç tipten biri olabildiğinde bir type switch, assertion zincirinin yerini alır. x.(type) yalnızca bir switch içinde geçerlidir.

Çıktı:

hi
integer 7
integer 8
3.14
nil
error: boom
unhandled []int

Bilmeye değer kurallar:

  • Tek tipli bir case'te x o tipe sahiptir. Birkaç tip listeleyen bir case'te ve default'ta x orijinal interface'in tipine (burada any) sahiptir.
  • Case'ler sırayla kontrol edilir. Bir değer birkaç interface'i karşılayabileceği için daha belirli interface'leri daha genişlerden önce koyun.
  • case nil yalnızca nil bir interface ile eşleşir, nil bir pointer tutan bir interface ile değil.
  • Bir type switch'te fallthrough yoktur.

errors.As: sarmalanmış hatalar için assertion

Hatalar çoğu zaman bağlamla sarmalanır: fmt.Errorf("load config: %w", err). Doğrudan bir type assertion yalnızca en dıştaki hataya bakar ve içtekini kaçırır. errors.As zinciri dolaşır.

Çıktı:

type assertion finds it: false
errors.As finds it: open /no/such/file

Hatalar üzerinde type assertion'ı yalnızca hatanın sarmalanmadığını bildiğinizde kullanın; bu da pratikte neredeyse hiçbir zaman demektir. errors.As, errors.Is ve kendi hata tiplerinizi tanımlamayı özel hatalar sayfası anlatıyor.

Assertion'lar, dönüşümler ve generics

ElinizdekiİstediğinizKullanın
intfloat64dönüşüm: float64(n)
bir int tutan anyint'in kendisiassertion: v.(int)
olası birkaç tipten biri olan anytipe göre dallanmaktype switch
sarmalanmış olabilecek bir errorbelirli bir hata tipierrors.As
birçok tip için çalışan bir fonksiyonderleme zamanı güvenliğigenerics

any ve type switch'lerle dolu kod çoğu zaman generics'in ya da düzgün bir interface'in niyeti daha iyi ifade edeceğine ve hataları derleme zamanında yakalayacağına işarettir.

Sık yapılan hatalar

  • Güvenilmeyen veride panic yapan biçimi kullanmak. Çözülmüş JSON, any tipindeki map değerleri, eklenti girdileri: her zaman virgül-ok.
  • Yanlış sayısal tipe assertion. JSON sayıları any içine float64 olarak çözülür, bu yüzden v.(int) onlarda başarısız olur.
  • Pointer saklanmışken değer tipine assertion. Interface *User tutuyorsa v.(User) başarısız olur. v.(*User) ile assertion yapın.
  • Hatalar üzerinde type assertion. errors.As kullanın.

Sıkça Sorulan Sorular

Go'da type assertion nedir?

x'in bir interface değeri olduğu x.(T) ifadesidir. T somut bir tipse x içinde saklanan değeri bir T olarak döndürür. T bir interface tipiyse saklanan değerin T'yi de gerçekleştirdiğini kontrol eder. Tek değerli biçim kontrol başarısız olduğunda panic olur; iki değerli biçim v, ok := x.(T) bunu ok içinde bildirir.

Go'da bir interface değerinin tipi nasıl kontrol edilir?

Bir type switch kullanın: switch v := x.(type) { case int: ...; case string: ...; default: ... }. Her case içinde v o case'in tipine sahiptir. Tek bir tip için virgül-ok assertion'ı s, ok := x.(string) daha kısadır. fmt.Printf("%T", x) hata ayıklama için tip adını yazdırır.

Go'da type assertion ile tip dönüşümü arasındaki fark nedir?

Bir dönüşüm T(x), float64(n) gibi bir tipteki değeri başka bir tipe çevirir; izin verilip verilmediğine derleyici karar verir ve çalışma zamanında başarısız olamaz. Bir assertion x.(T) yalnızca interface değerleri üzerinde çalışır ve içinde hangi tipin saklandığını çalışma zamanında kontrol eder. Bir int tutan any için int(x) yazamazsınız; x.(int) gerekir.

Hata tiplerini kontrol etmek için type assertion kullanmalı mıyım?

Hayır. errors.As(err, &target) kullanın. Doğrudan bir assertion err.(*MyError) yalnızca en dıştaki hataya bakar, bu yüzden hata fmt.Errorf("...: %w", err) ile sarmalandığı anda başarısız olur. errors.As sarmalama zincirini dolaşır.

Coddy programming languages illustration

Coddy ile kodlamayı öğren

BAŞLA