如何将一个go方法转换为一个函数?

huangapple go评论75阅读模式
英文:

How do I convert a go method to a func?

问题

我有一个包级函数(Frob),它接受一个函数作为参数。对于函数参数,我想传递一个具有特定结构实例作为接收器(myFrob)的方法(FrobMethod)。

我发现唯一的方法是使用捕获目标结构的func字面值/闭包。这需要重复func签名和参数,这似乎太冗长了。有更好的方法吗?

package main

import "fmt"

func Frob(frobber func(int) string) {
    fmt.Printf("Frob %s\n", frobber(42))
}

type MyFrob struct {
    Prefix string
}

func (m MyFrob) FrobMethod(n int) string {
    return fmt.Sprintf("%s %d", m.Prefix, n)
}

func main() {
    myFrob := MyFrob{Prefix: "Hello"}

    // C# 允许这样做:
    //
    // Frob(myFrob.FrobMethod)

    Frob(func(n int) string {
        return myFrob.FrobMethod(n)
    })
}

...一个真实世界的例子是net/http中的HandleFunc
英文:

I have a package-level function (Frob) that takes a function as an argument. For the function argument, I want to pass in a method (FrobMethod) with a particular struct instance as the receiver (myFrob).

The only way I've found to accomplish this is to use a func literal/closure that captures the target struct. That requires repeating the func signature and arguments, which seems too verbose. Is there a better way?

package main

import "fmt"

func Frob( frobber func( int ) ( string ) ) {
    fmt.Printf( "Frob %s\n", frobber( 42 ) )
}

type MyFrob struct {
    Prefix string
}

func ( m MyFrob ) FrobMethod( n int ) ( string ) {
    return fmt.Sprintf( "%s %d", m.Prefix, n )
}

func main() {

    myFrob := MyFrob { Prefix: "Hello" }

    // C# allows something like this:
    //
    //Frob( myFrob.FrobMethod )

    Frob( func ( n int ) ( string ) {
        return myFrob.FrobMethod( n )
    } )
}

...a real-world example of this is HandleFunc in net/http.

答案1

得分: 4

在我看来,在这种情况下,习惯用法的Go应该使用接口而不是函数:

package main

import "fmt"

type Frobber interface {
    FrobMethod(int) string
}

func Frob(frobber Frobber) {
    fmt.Printf("Frob %s\n", frobber.FrobMethod(42))
}

type MyFrob struct {
    Prefix string
}

func (m MyFrob) FrobMethod(n int) string {
    return fmt.Sprintf("%s %d", m.Prefix, n)
}

func main() {
    myFrob := MyFrob{Prefix: "Hello"}
    Frob(myFrob)
}

net/http中的HandleFunc函数是Handle函数的一个包装器,它接受一个接口参数。

英文:

In my opinion, idiomatic Go should use an interface instead of a function in this case:

package main
                                                                                                                                           
import "fmt"

type Frobber interface {
    FrobMethod(int) string
}

func Frob(frobber Frobber) {
    fmt.Printf("Frob %s\n", frobber.FrobMethod(42))
}

type MyFrob struct {
    Prefix string
}

func (m MyFrob) FrobMethod(n int) string {
    return fmt.Sprintf("%s %d", m.Prefix, n)
}

func main() {
    myFrob := MyFrob{Prefix: "Hello"}
    Frob(myFrob)
}

The function HandleFunc in net/http is a wrapper for function Handle which takes an interface argument.

答案2

得分: 1

虽然Go允许您创建将匿名函数分配给变量并传递它们的方式,但解决这个问题的另一种方法是利用接口。

package main

import "fmt"

type Frobber interface {
    Frob(int) string
}

type MyFrob struct {
    Prefix string
}

func (m MyFrob) Frob(n int) string {
    return fmt.Sprintf("%s %d", m.Prefix, n)
}

func Frob(f Frobber) {
    fmt.Printf("Frob %s\n", f.Frob(42))
}

func main() {
    myFrob := MyFrob{Prefix: "Hello"}
    Frob(myFrob)
}

在面向对象的语言中,您可以直接传递一个方法,但Go不是面向对象的。您必须从头开始重新思考,并不要试图像其他语言那样编写代码。我从Python转过来时也有同样的问题。

顺便说一下,我喜欢Go,并且正在积极努力提高我的技能,将其作为我的工具之一。回应评论中的@Jeremy,我只是在说Go不是面向对象,因为Go团队并没有完全支持它,它更常被称为过程化,并且它具有来自其他被认为是面向对象的语言的混合元素。

英文:

While Go does allow you to create anonymous function assignments to variables and pass them around, another way to approach this problem is to make use of interfaces.

package main

import "fmt"

type Frobber interface {
    Frob(int) string
}

type MyFrob struct {
    Prefix string
}

func (m MyFrob) Frob(n int) string {
    return fmt.Sprintf("%s %d", m.Prefix, n)
}

func Frob(f Frobber) {
    fmt.Printf("Frob %s\n", f.Frob(42))
}

func main() {
    myFrob := MyFrob {Prefix: "Hello"}
    Frob(myFrob)
}

In an object oriented language, you would be able to just pass a method around, but Go isn't OO. You have to start your brain over from the beginning and not try to write the code like you would in other languages. I have that same problem coming from Python.

By the way, I love Go and am actively trying to improve my skills with it as a tool in my tool belt. In response to @Jeremy in the comments, I am only stating that Go is not OO because its not firmly supported to be such by the Go team, and its more commonly referred to as procedural, and, having a mixture of elements from other languages that are themselves considered to be OO

答案3

得分: 1

从Go 1.1版本开始,C#风格的方法引用可以使用:

Frob( myFrob.FrobMethod )

请参阅Go语言规范中的Method expressions部分。

英文:

As of Go 1.1, the C#-style method reference works:

Frob( myFrob.FrobMethod )

See the Method expressions section of the Go Language Specification.

huangapple
  • 本文由 发表于 2012年4月1日 02:24:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/9958489.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定