很抱歉,我不能在问题标题中更具体地说明,但我在阅读一些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处理程序)和(s *GracefulServer)是什么意思?考虑到括号之间的内容,整个函数声明意味着什么?

Edit

This is not a duplicate of Whats the difference of functions and methods in Go? : this question came to me because I didn't know what the things in parenthesis before the function name were, not because I wondered what was the difference between functions and methods... if I knew that this declaration was a method I wouldn't have had this question in the first place. If someone has the same doubt as me one day, I don't believe she will go searching for "golang methods" because she doesn't know that this is the case. It would be like wondering what the letter "sigma" means before a mathematical expression (not knowing it means summation) and someone says it's a duplicate of what's the difference between summation and some other thing.

同样,对这个问题(“它是一个接收器”)的简短回答也不能回答“函数和方法之间的区别是什么”。


当前回答

This is called the 'receiver'. In the first case (h handler) it is a value type, in the second (s *GracefulServer) it is a pointer. The way this works in Go may vary a bit from some other languages. The receiving type, however, works more or less like a class in most object-oriented programming. It is the thing you call the method from, much like if I put some method A inside some class Person then I would need an instance of type Person in order to call A (assuming it's an instance method and not static!).

One gotcha here is that the receiver gets pushed onto the call stack like other arguments so if the receiver is a value type, like in the case of handler then you will be working on a copy of the thing you called the method from meaning something like h.Name = "Evan" would not persist after you return to the calling scope. For this reason, anything that expects to change the state of the receiver needs to use a pointer or return the modified value (gives more of an immutable type paradigm if you're looking for that).

以下是规范中的相关部分;https://golang.org/ref/spec#Method_sets

其他回答

如果你熟悉c#扩展方法,

go方法(带有特殊接收参数的函数)。

func (v Vertex) Abs() float64

是不是类似c#的扩展方法

static float Abs( this Vertex v);

值类型和指针之间的区别在evanmcdonnal的回答中有描述

This is called the 'receiver'. In the first case (h handler) it is a value type, in the second (s *GracefulServer) it is a pointer. The way this works in Go may vary a bit from some other languages. The receiving type, however, works more or less like a class in most object-oriented programming. It is the thing you call the method from, much like if I put some method A inside some class Person then I would need an instance of type Person in order to call A (assuming it's an instance method and not static!).

One gotcha here is that the receiver gets pushed onto the call stack like other arguments so if the receiver is a value type, like in the case of handler then you will be working on a copy of the thing you called the method from meaning something like h.Name = "Evan" would not persist after you return to the calling scope. For this reason, anything that expects to change the state of the receiver needs to use a pointer or return the modified value (gives more of an immutable type paradigm if you're looking for that).

以下是规范中的相关部分;https://golang.org/ref/spec#Method_sets

这意味着ServeHTTP不是一个独立的函数。函数名前的括号是定义这些函数操作的对象的Go方式。本质上,ServeHTTP是类型处理程序的方法,可以使用任何类型处理程序的对象调用,比如h。

h.ServeHTTP(w, r)

他们也被称为接收器。有两种定义方法。如果你想修改接收者,使用一个指针:

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

如果你不需要修改接收者,你可以将接收者定义为如下值:

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

这个来自围棋游乐场的例子演示了这个概念。

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}