関数宣言構文:関数名の前の括弧内のもの


248

質問のタイトルを具体的に説明できなかったのは残念ですが、Goコードを読んでいて、次の形式の関数宣言が見つかりました。

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

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

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

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

何が(h handler)(s *GracefulServer)括弧の平均値との間には?括弧内の意味を考慮して、関数宣言全体はどういう意味ですか?

編集する

これはGoの関数とメソッドの相違点の重複ではありませんか?:この質問は、関数名の前の括弧内の内容が何であるかがわからなかったため、そして関数とメソッドの違いは何だろうと思ったために出てきました...この宣言がメソッドであることがわかっていれば、そもそもこの質問はありませんでした。誰かが私と同じ疑問をいつか持っているとしたら、彼女が「golangメソッド」を探しに行くとは思えません。それは、数式の前に「シグマ」という文字が何を意味するのか(合計を意味することを知らない)疑問に思うようなものであり、誰かがそれが合計と他の何かとの違いは何であるかを複製していると言います。

また、この質問に対する短い答え(「それはレシーバーです」)は、「関数とメソッドの違いは何ですか」に対する答えではありません。


27
次に、@ Volkerは、stackoverflowのGoの人々は、Tour of Goにない質問にのみ答えるという免責事項を書きました。Haskellコミュニティでは、Haskell のリストから要素を取得するにはどうすればよいnですか?などの質問をすることができます。は、「はじめにHaskell for Great Good学ぶ」の「はじめに」にあり、大騒ぎせずに質問に答えることができます。
MarcusViníciusMonteiro

23
この質問があったとき、私は最初にゴーツアーに行きました。私はすべての「関数」タイトルをチェックしましたが、これをカバーする例はありませんでした。tour.golang.org/basics/4 tour.golang.org/basics/5メソッドとインターフェースを拡張する方法がわからない場合、「メソッドは関数」というタイトルは表示されません。この質問は、Googleのインデックス作成に有効で優れています。重複する旗の狂信者は明るくなる必要があります。
Bruno Bronosky 2018

14
答えを見つけるのに十分だったので、質問を具体的に説明しなかったことに感謝します。
デビッドK

1
あなたは私が検索したものを正確に尋ねました、それは有効な質問です。ありがとうございました。私はあらゆる種類の関数定義を読み、誰もこれを説明しませんでした。私はまだnubeの質問を書いてみましたが、これを見つけました。
Ajak6

回答:


199

これは「レシーバー」と呼ばれます。前者の場合(h handler)は値型(s *GracefulServer)であり、後者の場合はポインタです。Goでのこの動作は、他の一部の言語とは少し異なる場合があります。ただし、受信タイプは、ほとんどのオブジェクト指向プログラミングのクラスのように機能します。それはあなたがメソッドを呼び出すものです、私がいくつAかのクラスにいくつかのメソッドを置いた場合と同じように、呼び出すためにPerson型のインスタンスが必要にPersonなりますA(それが静的ではなくインスタンスメソッドであると仮定します!)

ここでの一つの落とし穴は、受信機は、受信機が値型であるかのように、の場合と同様に、他の引数のようなコールスタックにプッシュされることをであるhandler、あなたはもののコピーで作業するあなたのような何かを意味するからメソッドを呼び出しh.Name = "Evan"ます呼び出しスコープに戻った後は保持されません。このため、レシーバーの状態を変更することが予想されるものはすべて、ポインターを使用するか、変更された値を返す必要があります(探している場合は、不変タイプのパラダイムをさらに提供します)。

これは、仕様の関連セクションです。https://golang.org/ref/spec#Method_sets


6
関連する仕様にリンクするための適切な説明と追加のカルマポイント
Marius Waldal

4
golangツアーにもかなり便利な例がいくつかありますtour.golang.org/methods/1
tw_hoff

90

これはServeHTTPスタンドアロン関数ではないことを意味します。関数名の前の括弧は、これらの関数が動作するオブジェクトを定義するGoの方法です。したがって、本質的にServeHTTPはタイプハンドラのメソッドであり、タイプハンドラの任意のオブジェクト(hなど)を使用して呼び出すことができます。

h.ServeHTTP(w, r)

それらはレシーバとも呼ばれます。それらを定義する方法は2つあります。レシーバーを変更する場合は、次のようなポインターを使用します。

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

レシーバーを変更する必要がない場合は、レシーバーを次のような値として定義できます。

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

Goプレイグラウンドのこの例は、概念を示しています。

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)

上記のプログラムの出力は次のとおりです。

&{0 0}
&{0 0}
&{5 7}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.