Arayüz (Interface)
Interface, belirli metodların imzalarını içeren bir veri türüdür. Bu metodları uygulayan herhangi bir veri türü, o interface’i gerçekleştirmiş olur. Diğer dillerden farklı olarak Go’da interface’ler, uygulama detaylarını içermek yerine sadece metodların imzalarını içerir.
Interface Nasıl Kullanılır?
Bir interface aşağıdaki gibi tanımlanabilir.
type Animal interface { Speak() string}Yukarıda bir Animal interface’i oluşturduk. Bir veri tipinin bu interface’i uygulaması için Speak() string imzasına sahip bir metodu olması gerekir.
Bu interface’i uygulayan 2 adet veri tipi oluşturalım.
type Dog struct{}
func (Dog) Speak() string { return "Woof!"}
type Cat struct{}
func (Cat) Speak() string { return "Meow!"}Yukarıdaki örneğe göre Dog ve Cat isminde 2 veri tipi oluşturduk. Bu 2 tip de Animal interface’ini uygulamak için Speak() string imzasına uygun metodlar içeriyor.
Bu duruma göre Animal interface’ine uygun bir veri tipi kabul eden yere nasıl nesne göndereceğimizi bakalım.
var a Animal
a = Dog{}
fmt.Println(a.Speak()) // Woof!
a = Cat{}
fmt.Println(a.Speak()) // Meow!Interface’ler polimorfizmi (çok-biçimlilik) desteklemek için kullanılır. Parametre olarak interface bekleyen bir fonksiyon, bu interface’i gerçekleştiren herhangi bir türü parametre olarak kabul edebilir.
package main
import "fmt"
type Animal interface { Speak() string}
type Dog struct{}
func (d Dog) Speak() string { return "Woof!"}
type Cat struct{}
func (c Cat) Speak() string { return "Meow!"}
func MakeAnimalSpeak(a Animal) { fmt.Println(a.Speak())}
func main() { dog := Dog{} cat := Cat{}
MakeAnimalSpeak(dog) // Woof! MakeAnimalSpeak(cat) // Meow!}Boş Interface
Boş interface, interface{} olarak tanımlanır ve tüm veri tiplerini temsil etmek için kullanılır. Çeşitli veri tipinden değişkenleri tek bir veri yapısında saklamak için kullanışlıdır.
package main
import "fmt"
func PrintAnything(i interface{}) { fmt.Println(i)}
func main() { PrintAnything(42) // 42 PrintAnything("hello") // hello PrintAnything(true) // true}Boş interface yerine diğer bir adı olan any veri tipini de kullanabiliriz.
func PrintAnything(i any) { fmt.Println(i)}any veri tipini go kaynak dosyalarından incelediğimizde, arkaplanda boş interface’in takma adı olduğunu görebiliriz.
96// any is an alias for interface{} and is equivalent to interface{} in all ways.97type any = interface{}Interface Üzerinde Tip İddiasında Bulunmak
Interface üzerinde tip iddiasında (type assertion) bulunarak, interface’i uygulayan veri tipinin kendisine ulaşabiliriz.
1package main2
3import "fmt"4
5type Animal interface {6 Speak() string7}8
9type Dog struct{}10
11func (Dog) Speak() string {12 return "Woof!"13}14
15type Cat struct{}16
17func (Cat) Speak() string {18 return "Meow!"19}20
21func MakeAnimalSpeak(a Animal) {22 dog, ok := a.(Dog)23 if ok {24 fmt.Println("Dog says", dog.Speak())25 return26 }27
28 cat, ok := a.(Cat)29 if ok {30 fmt.Println("Cat says", cat.Speak())31 }32}33
34func main() {35 var a Animal36 a = Dog{}37 MakeAnimalSpeak(a) // Dog says Woof!38 a = Cat{}39 MakeAnimalSpeak(a) // Cat says Meow!40}- ve 28. satırlarda
adeğişkeni içerisindeAnimalinterface’ini uygulayan veri tiplerininDogveCatolup olmadığını, tip iddiasında bulunarak öğrenmiş olduk.
Yukarıdaki örneği switch kullarak da yapabilirdik.
func MakeAnimalSpeak(a Animal) { switch x := a.(type) { case Dog: fmt.Println("Dog says", x.Speak()) case Cat: fmt.Println("Cat says", x.Speak()) }}Yukarıdaki örneğe göre, a’nın tipi Dog olduğunda Dog case’i içerisinde x değişkeni Dog veri tipinin metodlarına sahip olacaktır. Benzer durum Cat veri tipi için de geçerli.
Veri tipi iddiasında bulunmanın diğer bir amacı, sadece Animal interface’inde belirtilen metodları kullanmak yerine, tip iddiasında bulunduğumuz tipe özel metodları da kullanabilmektir.
Örneğin,
1package main2
3import "fmt"4
5type Animal interface {6 Speak() string7}8
9type Dog struct{}10
11func (Dog) Speak() string {12 return "Woof!"13}14
15func (Dog) TailWag() {16 fmt.Println("Tail wagging!")17}18
19func main() {20 var a Animal21 a = Dog{}22
23 fmt.Println(a.Speak()) // Woof!24
25 dog, ok := a.(Dog)26 if ok {27 dog.TailWag() // Tail wagging!28 }29}