首页 文章

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

提问于
浏览
122

我在问题 Headers 中更具体,但我正在阅读一些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?的重复:这个问题来找我,因为我没有首先提出这个问题 . 如果某人有一天和我有同样的疑问,我就不会知道情况就是这样 . 这就像想知道"sigma"在数学表达式之前的含义(不知道它意味着求和),有人说它总和与其他东西之间的区别 .

此外,这个问题的简短回答(“它是接收者”)无法回答“功能和方法之间的区别” .

2 回答

  • 50

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

    这里有一个问题是接收器像其他参数一样被推入调用堆栈,所以如果接收器是一个值类型,就像在 handler 的情况下那么你将从一个你所谓的方法的副本开始工作返回调用范围后 h.Name = "Evan" 将不会保留 . 出于这个原因,任何期望改变接收器状态的东西都需要使用指针或返回修改后的值(如果你正在寻找它,则给出更多的不可变类型范例) .

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

  • 102

    这意味着 ServeHTTP 不是一个独立的功能 . 函数名之前的括号是定义这些函数将在其上运行的对象的Go方式 . 所以,基本上 ServeHTTP 是一个类型处理程序的方法,可以使用任何类型处理程序的对象(例如h)来调用 .

    h.ServeHTTP(w, r)
    

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

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

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

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

    来自Go playground的This示例演示了这个概念 .

    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}
    

相关问题