ProgramlamaGo geliştirici

Go'da özel (kullanıcı tanımlı) türler ve yöntemler nasıl uygulanır ve kullanılabilir, bunların tanımında hangi incelikler vardır?

Hintsage yapay zeka asistanı ile mülakatları geçin

Cevap.

Sorunun geçmişi:

Go'da sıklıkla yerleşik türlerin yetersiz kaldığı durumlar ortaya çıkar ve bu nedenle kendi veri türünüzü ve mantığı kapsamak ve işlevselliği genişletmek için yöntemleri tanımlamanız gerekir. Bu, özel türlerin (type) ve yöntemlerin (func (r Receiver) MethodName()) oluşturulmasıyla gerçekleştirilir.

Sorun:

Yeni başlayan geliştiriciler genellikle yeni bir türün mevcut bir türden nasıl oluşturulacağını karıştırıyor. Yöntemleri doğru bir şekilde nasıl uygulayacaklarını biliyorlar mı? Kopyalama, değer/işaretçi geçişi sorunu nasıl çözülüyor? Erişim kapsamı, tür alıcısı ve gömülü yapılarla çalışırken hatalar yapıyorlar.

Çözüm:

Kendi türünüzü tanımlamak için type anahtar kelimesi kullanılır. Yöntemler, ara alıcı (receiver) kullanılarak uygulanır - bu, arayüzlerle çalışmak için önemlidir.

Kod örneği:

type MyInt int func (m MyInt) Double() int { return int(m) * 2 } // Yapılar için: type User struct { Name string Age int } func (u *User) Birthday() { u.Age++ } var u = User{"Alice", 30} u.Birthday() // Age = 31

Anahtar özellikler:

  • Kullanıcı tanımlı türler, temel türlerin yöntemlerini miras almaz.
  • Pointer alıcılı (pointer receiver) yöntemler durumu değiştirebilir, değer alıcılı (value receiver) olanlar kopyayla çalışır.
  • Arayüzler için yöntemler "somut" türde tanımlanmalıdır, takma adda değil.

Sorularla ilgili tuzaklar.

Kullanıcı tanımlı türler temel türlerin yöntemlerini miras alır mı?

Hayır. Eğer type MyInt int tanımlarsanız, MyInt int yöntemlerine sahip değildir. Örneğin, String() çağrısı veya temel türün diğer yöntemleri çalışmaz.

Tür takma adları için yöntemler tanımlamak mümkün mü?

Takma ad (type MyType = ExistingType) için yöntem eklemek mümkün değildir. Yöntemler yalnızca yeni türler için (type MyType ExistingType) tanımlanabilir, takma adlar için değil.

Hangi alıcıyı kullanmalıyım: işaretçi mi yoksa değer mi?

Eğer yöntem, nesneyi değiştirmesi gerekiyorsa, işaretçi kullanmak daha iyidir. Değer alıcısı yapıyı kopyalar, bu beklenmedik davranışlara yol açabilir, özellikle eğer yapı dilimlerine ve haritalara sahip olursa.

Kod örneği:

type Counter struct { value int } func (c *Counter) Inc() { c.value++ } func main() { c := Counter{} c.Inc() // yalnızca işaretçi ile yöntem değeri değiştirir }

Tipik hatalar ve anti-paternhlar

  • Alias/yeni tür ile ilgili hata yapmak - takma adın yöntemlerle genişletilebileceğini düşünmek.
  • "Setter"'lar için değer alıcısı kullanmak ve çalışmayan kod almak.
  • Yerleşik yöntemlerin otomatik olarak özel bir türe geçeceğini beklemek.

Gerçek hayattan bir örnek

Olumsuz durum

Bir programcı type MySlice []int tanımladı ve []int'nin, örneğin, append gibi yöntemlerinin MySlice türü üzerinde çalışacağını bekliyordu. Sonuç olarak, hiçbir yöntemin olmadığını ve MySlice'e doğrudan []int olarak erişilemeyeceğini anladı.

Artılar:

  • Başlangıçta yeniden kullanım konforlu görünüyordu.

Eksiler:

  • Beklenmedik uyumsuzluk hataları ve yöntemlerle ilgili rahatsızlıklar.

Olumlu durum

type Counter int tanımlandı ve Inc yöntemi ile birlikte kullanıldı, bu da programın birkaç yerinde ortak mantıkla kullanılmasını sağladı ve kodun tekrarını önledi.

Artılar:

  • Mantığın net kapsülasyonu. Test edilmesi kolay.

Eksiler:

  • Yerleşik int türünden bazı yardımcı işlevlerin manuel olarak uygulanması gerekti.