Arabirimler, bu konuyla ilgili derinlemesine bir yanıt vermek için çok büyük bir konudur, ancak bazı şeyleri kullanımlarını açık hale getirmektedir.
Arabirimler, aracı aracıdır. Bunları kullanmak ya da kullanmamak size kalmış, ancak kodları daha açık hale getirebilir ve paketler ya da istemciler (kullanıcılar) ve sunucular (sağlayıcılar) arasında iyi bir API sağlayabilirler.
Evet, kendi struct
türü oluşturabilir, ve örneğin, kendisine yöntemleri "attach" olabilir: Biz zaten yukarıdaki kodda tekrar geçmeye görebilirsiniz
type Cat struct{}
func (c Cat) Say() string { return "meow" }
type Dog struct{}
func (d Dog) Say() string { return "woof" }
func main() {
c := Cat{}
fmt.Println("Cat says:", c.Say())
d := Dog{}
fmt.Println("Dog says:", d.Say())
}
: Her iki Cat
yaparken ve Dog
bir şey söyle. Hayvan ile aynı türde varlık olarak ele alabilir miyiz?Pek sayılmaz. Her ikisini de interface{}
olarak ele alabildiğimizden emin olabiliriz, ancak bunu yaparsak,türünde bir değer tanımlayamadığı için Say()
yöntemini kullanamıyoruz. Yukarıdaki iki türde de benzeri var: Say()
aynı imzaya sahip (parametre ve sonuç türleri). Biz bir arayüz ile bu yakalayabilir:
type Sayer interface {
Say() string
}
arayüzü onların uygulanmasını sadece imza yöntemlerden içerir, ancak değil.
Git yönteminde, türünde bir türünün, arabirimi, arabirimin bir üst kümesi ise, bir arabirimi uygulayacağını unutmayın. Niyet beyanı yoktur. Ne anlama geliyor? Önceki Cat
ve Dog
türlerimiz bu Sayer
ara yüzünü zaten uygulamış olsalar bile, bu arayüz tanımı daha önce yazdığımızda bile mevcut değildi ve bunları işaretlemek için bunlara dokunmadık. Sadece yaparlar.
Arabirimler davranışı olarak belirtir. Bir arabirimi uygulayan bir tür, bu türün, arabirimin "reçete ettiği" tüm yöntemlere sahip olduğu anlamına gelir. Her ikisi de Sayer
uygulandığından beri, her ikisi de Sayer
değeri olarak ele alabilir, bunların ortak noktaları vardır. birlik içinde hem işleyebilir Bakın nasıl:
animals := []Sayer{c, d}
for _, a := range animals {
fmt.Println(reflect.TypeOf(a).Name(), "says:", a.Say())
}
(bölümünü yansıtan tür adı almak için tek olduğunu, şu andan itibaren çok onun yapmazlar.)
önemli bir parçasıdır Cat
ve Dog
'u aynı tür (bir arabirim türü) olarak ele alabildiğimiz ve onlarla çalışabileceğimiz/kullanabileceğimiz. Eğer bir Say()
yöntemle ek türleri oluşturmak için hızlı bir şekilde olsaydı, bunlar Cat
ve Dog
yanında hizaya olabilir:
type Horse struct{}
func (h Horse) Say() string { return "neigh" }
animals = append(animals, Horse{})
for _, a := range animals {
fmt.Println(reflect.TypeOf(a).Name(), "says:", a.Say())
}
Diyelim ki bu tür ile çalışır diğer kod yazmak istediğinizi varsayalım. Bir yardımcı işlevi:
func MakeCatTalk(c Cat) {
fmt.Println("Cat says:", c.Say())
}
Evet, yukarıdaki fonksiyon Cat
ile ve başka bir şey ile çalışır. Benzer bir şey istiyorsanız, her tür için yazmanız gerekir. Bunun ne kadar kötü olduğunu söylemeye gerek yok.
Evet, interface{}
bir argüman almak ve yardımcı fonksiyonların sayısını azaltmak, ama yine de gerçekten çirkin görünüyor ediyorum type assertion veya type switches kullanımı yazabilirim.
Çözüm? Evet, arayüzler. Basitçe onunla yapmak istiyorum davranışı tanımlayan bir arayüz türünde bir değer almak için işlev bildirir ve hepsi bu:
func MakeTalk(s Sayer) {
fmt.Println(reflect.TypeOf(s).Name(), "says:", s.Say())
}
Sen Cat
değeri ile Dog
, Horse
veya herhangi Bu fonksiyonu çağırabilirsiniz diğer tür 'şimdiye kadar bilmiyorum, bu bir Say()
yöntemine sahip. Güzel.
Bu örnekleri, Go Playground adresinde deneyin.
bilinmeyen yapı JSON unzshall nasıl olacak? ya da orada olmasa fmt.Printf nasıl çalışır? – YOU
iyi çalışmıyor, eğer orada değilse, nasıl çalışacağını kastediyorsunuz? fmt – nikoss
'dan dışa aktarılır. [Git: Arayüzün anlamı nedir?} (http://stackoverflow.com/questions/23148812/go-whats-the-meaning-of-interface) – molivier