首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >函数声明语法:函数名称前的括号中的内容

函数声明语法:函数名称前的括号中的内容
EN

Stack Overflow用户
提问于 2015-12-02 06:56:53
回答 3查看 46.9K关注 0票数 385

很抱歉,我不能在问题标题中更具体,但我正在阅读一些Go代码,我遇到了以下形式的函数声明:

代码语言:javascript
复制
func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    ...
}

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

代码语言:javascript
复制
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“在数学表达式之前是什么意思(不知道它意味着求和),而有人说它是求和和其他东西之间的区别的副本。

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

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2015-12-02 07:03:31

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

这里的一个问题是,接收器像其他参数一样被推送到调用堆栈上,所以如果接收器是值类型,比如handler,那么你将处理你调用的方法的副本,这意味着在你返回调用作用域后,像h.Name = "Evan"这样的东西将不会持续存在。因此,任何想要改变接收器状态的东西都需要使用一个指针或者返回修改后的值(如果你正在寻找的话,它提供了更多的不可变类型范例)。

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

票数 294
EN

Stack Overflow用户

发布于 2015-12-18 15:20:41

这意味着ServeHTTP不是一个独立的函数。函数名前面的括号是定义这些函数将在其上操作的对象的方式。因此,本质上,ServeHTTP是一种handler类型的方法,可以使用任何handler类型的对象来调用。

代码语言:javascript
复制
h.ServeHTTP(w, r)

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

代码语言:javascript
复制
func (s *MyStruct) pointerMethod() { } // method on pointer

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

代码语言:javascript
复制
func (s MyStruct)  valueMethod()   { } // method on value

Go游乐场中的This示例演示了这一概念。

代码语言:javascript
复制
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)

上述程序的输出为:

代码语言:javascript
复制
&{0 0}
&{0 0}
&{5 7}
票数 130
EN

Stack Overflow用户

发布于 2021-03-13 06:05:50

如果您熟悉c# extension methods

go方法(a function with a special receiver argument),例如

代码语言:javascript
复制
func (v Vertex) Abs() float64

类似于c#扩展方法

代码语言:javascript
复制
static float Abs( this Vertex v);

值类型和指针之间的区别在evanmcdonnal’s answer中有说明

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/34031801

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档