İşlev bildirimi sözdizimi: işlev adından önce parantez içindeki şeyler


249

Üzgünüm soru başlığı daha belirgin olamazdı, ama bazı Go kodu okuyordu ve bu formun işlev bildirimleri ile karşılaştı:

func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    ...
}

dan https://github.com/mattermost/platform/blob/master/api/context.go

func (s *GracefulServer) BlockingClose() bool {
    ...
}

dan https://github.com/braintree/manners/blob/master/server.go

Ne yapar (h handler)ve (s *GracefulServer)parantez ortalama arasındaki? Parantez arasındaki şeylerin anlamı dikkate alınarak, tüm işlev bildirimi ne anlama gelir?

Düzenle

Bu, Go'daki işlevler ve yöntemler arasındaki farkın bir kopyası değil mi? : Bu soru bana geldi çünkü işlev adından önce parantez içindeki şeylerin ne olduğunu bilmiyordum, işlevler ve yöntemler arasındaki farkın ne olduğunu merak ettiğim için değil ... eğer bu bildirimin bir yöntem olduğunu bilseydim İlk etapta bu soruyu sormadım. Birisi bir gün benimle aynı şüpheye sahipse, "golang yöntemleri" aramaya gideceğine inanmıyorum çünkü durumun böyle olduğunu bilmiyor. Matematiksel bir ifadeden önce (sigma anlamına geldiğini bilmeden) “sigma” harfinin ne anlama geldiğini merak etmek gibi görünüyor ve birisi bunun toplam ile başka bir şey arasındaki farkın bir kopyası olduğunu söylüyor.

Ayrıca, bu sorunun kısa cevabı ("bir alıcı") "fonksiyonlar ve yöntemler arasındaki farkın ne olduğu" şeklinde bir cevap değildir.


27
@ Volker daha sonra stackoverflow'daki Go kişilerinin yalnızca Go Tour'da olmayan soruları yanıtladığını söyleyen bir sorumluluk reddi beyanı koydu. Haskell topluluğunda, insanlar Haskell'deki listeden nasıl bu nöğeyi alabilirim ? , Büyük İyi için bir Haskell öğrenin ve bu konuda bir karışıklık olmadan sorularını yanıtlayın.
Marcus Vinícius Monteiro

23
Bu soruyu sorduğumda, önce Go Tour'a gittim. Tüm "İşlev" başlıklarını kontrol ettim ve örneklerin hiçbiri bunu kapsamıyordu. tour.golang.org/basics/4 tour.golang.org/basics/5 Yöntemleri ve arayüzleri genişletmeyi bilmiyorsanız, "Yöntemler işlevlerdir" başlığını görmezsiniz. Bu soru Google dizinleme için geçerli ve harika. Yinelenen bayrak zealotlarının aydınlanması gerekiyor.
Bruno Bronosky

14
Sorunuzda spesifik olmadığınız için teşekkürler, çünkü cevabı bulmama yardım etmek yeterliydi!
David K

1
Tam olarak ne aradığımı sordunuz, geçerli bir soru. Teşekkür ederim. Her türlü fonksiyon tanımını okudum ve kimse bunu açıklamadı. Hala nube sorumu yazmayı denedim ve buldum.
Ajak6

Yanıtlar:


200

Buna 'alıcı' denir. İlk durumda (h handler)bir değer türüdür, ikincisinde (s *GracefulServer)bir işaretçi olur. Bunun Go'da çalışma şekli diğer dillerden biraz farklı olabilir. Ancak alıcı türü, çoğu nesne yönelimli programlamada az çok bir sınıf gibi çalışır. Bu yöntemi çağırmak şey, çok Abazı sınıf tarafında bazı yöntem koymak Persono zaman (örneğin bir örnek yöntemi ve statik değil!) Varsayalım Personçağırmak için tür bir örnek gerekir A.

Burada bir tane var, alıcının diğer argümanlar gibi çağrı yığınına itilmesi, böylece alıcı bir değer tipiyse, handlero zaman olduğu gibi, yöntem olarak adlandırdığınız şeyin bir kopyası üzerinde h.Name = "Evan"çalışacaksınız. arama kapsamına döndükten sonra da devam etmez. Bu nedenle, alıcının durumunu değiştirmeyi bekleyen, bir işaretçi kullanması veya değiştirilen değeri döndürmesi gerekir (eğer arıyorsanız, daha çok değişmez tipte bir paradigma verir).

İşte spesifikasyondan ilgili bölüm; https://golang.org/ref/spec#Method_sets


6
İlgili spesifikasyona bağlantı için iyi bir açıklama ve ekstra karma puanlar
Marius Waldal

4
Golang turunun da oldukça faydalı örnekleri var tour.golang.org/methods/1
tw_hoff

90

Bu ServeHTTP, bağımsız bir işlev olmadığı anlamına gelir . İşlev adından önceki parantez, bu işlevlerin üzerinde çalışacağı nesneyi tanımlamanın Go yoludur. Bu nedenle, esasen ServeHTTPbir tür işleyici yöntemidir ve h tipi tür işleyici herhangi bir nesne kullanılarak çağrılabilir.

h.ServeHTTP(w, r)

Bunlara alıcı da denir. Onları tanımlamanın iki yolu vardır . Alıcıyı değiştirmek istiyorsanız aşağıdaki gibi bir işaretçi kullanın:

func (s *MyStruct) pointerMethod() { } // method on pointer

Alıcıyı değiştirmeniz gerekmiyorsa, alıcıyı aşağıdaki gibi bir değer olarak tanımlayabilirsiniz:

func (s MyStruct)  valueMethod()   { } // method on value

Go oyun alanından gelen bu örnek konsepti göstermektedir.

package main

import "fmt"

type Mutatable struct {
    a int
    b int
}

func (m Mutatable) StayTheSame() {
    m.a = 5
    m.b = 7
}

func (m *Mutatable) Mutate() {
    m.a = 5
    m.b = 7
}

func main() {
    m := &Mutatable{0, 0}
    fmt.Println(m)
    m.StayTheSame()
    fmt.Println(m)
    m.Mutate()
    fmt.Println(m)

Yukarıdaki programın çıktısı:

&{0 0}
&{0 0}
&{5 7}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.