函数声明语法:函数名前括号内的东西

新手上路,请多包涵

很抱歉我不能在问题标题中更具体,但我正在阅读一些 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) 是什么意思?考虑到括号之间事物的含义,整个函数声明是什么意思?

编辑

这不是 Whats the difference of functions and methods in Go 的副本? :这个问题来找我是因为我不知道函数名之前括号中的东西是什么,不是因为我想知道函数和方法之间有什么区别……如果我知道这个声明是一个方法我就不会’一开始就没有这个问题。如果有一天有人和我有同样的疑问,我不相信她会去寻找“golang方法”,因为她不知道是这样的。这就像想知道数学表达式前的字母“sigma”是什么意思(不知道它意味着求和),有人说它是求和与其他事物之间区别的重复。

此外,对这个问题的简短回答(“它是一个接收者”)并不能回答“函数和方法之间有什么区别”。

原文由 Marcus Vinícius Monteiro 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

这被称为“接收器”。在第一种情况下 (h handler) 它是一个值类型,在第二种情况下 (s *GracefulServer) 它是一个指针。这在 Go 中的工作方式可能与其他一些语言略有不同。然而,接收类型的工作方式或多或少类似于大多数面向对象编程中的类。这是你调用方法的东西,很像如果我把一些方法 A 放在一些类 Person 那么我需要一个类型的实例 Person 为了调用 A (假设它是一个实例方法而不是静态的!)。

这里的一个陷阱是接收者像其他参数一样被推入调用堆栈,所以如果接收者是一个值类型,就像 handler 的情况一样,那么你将处理你调用的东西的副本返回调用范围后,方法的含义类似于 h.Name = "Evan" 将不会持续存在。出于这个原因,任何希望改变接收者状态的东西都需要使用指针或返回修改后的值(如果你正在寻找的话,会提供更多的不可变类型范例)。

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

原文由 evanmcdonnal 发布,翻译遵循 CC BY-SA 4.0 许可协议

这意味着 ServeHTTP 不是独立函数。函数名前的括号是 Go 定义这些函数将运行的对象的方式。因此,本质上 ServeHTTP 是一种类型处理程序的方法,可以使用类型处理程序的任何对象(例如 h)调用。

 h.ServeHTTP(w, r)

它们也被称为接收器。 两种定义它们的方法。如果要修改接收器,请使用如下指针:

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

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

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

Go playground 中的 这个 例子演示了这个概念。

 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}

原文由 Abhishek Nalin 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
logo
Stack Overflow 翻译
子站问答
访问
宣传栏