从Go闭包中返回一个方法。

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

Return a method from a Go closure

问题

我想要能够动态生成一个方法ApiName,用于以下结构体:

type SomeCustomSObject struct {
    sobjects.BaseSObject
}

我想要为以下接口实现该方法:

type SObject interface {
    ApiName() string
    ExternalIdApiName() string
}

我希望能够按照以下方式动态创建该方法:

func createApiNameMethod(name string) <返回类型> {
    return func(t *SomeCustomSObject) string {
        return name
    }
}

我知道上面的代码不起作用,但在Go语言中有没有实现这个目标的方法呢?

英文:

I want to be able to dynamically generate a method ApiName for the following struct:

type SomeCustomSObject struct {
	sobjects.BaseSObject
}

The interface I want to implement the method for is as follows:

type SObject interface {
    ApiName() string
    ExternalIdApiName() string
}

I would like to dynamically create the method as follows:

func createApiNameMethod(name, string) &lt;return type&gt; {
    return func (t *SomeCustomSObject) ApiName() string {
	        return name
        }
} 

I know the code above does not work, but is there anyway to acheive this in Go?

答案1

得分: 4

你不能在函数内部定义方法,详细信息请参见https://stackoverflow.com/questions/28252117/golang-nested-class-inside-function/28252170#28252170。

你可以创建一个SObject的实现,该实现能够在自己的实现中调用自定义函数。创建这样一个“代理”实现的简单方法是使用一个结构体,其字段是函数类型,与方法的类型匹配(没有接收者),并在该结构体上实现方法。方法的实现可以简单地将调用转发到存储在结构体字段中的函数值,并且如果适当的字段未设置,则可以具有默认行为。你可以更改函数字段的值,方法的行为将是动态的。

这是一个示例:

type sobjimpl struct {
    apiName           func() string
    externalIdApiName func() string
}

func (s *sobjimpl) ApiName() string {
    if s.apiName == nil {
        return "<not implemented>"
    }
    return s.apiName()
}

func (s *sobjimpl) ExternalIdApiName() string {
    if s.externalIdApiName == nil {
        return "<not implemented>"
    }
    return s.externalIdApiName()

}

func createApiNameMethod(name string) SObject {
    return &sobjimpl{
        apiName: func() string { return name },
    }
}

测试它:

so := createApiNameMethod("testName")
fmt.Println(so.ApiName())

输出结果如预期(在Go Playground上尝试):

testName

当然,在这个简单的示例中,sobjimpl.apiName函数字段可以完全省略,只需存储name并从sobjimpl.ApiName()返回即可。但是该示例展示了如何在运行时选择将作为实现方法调用的函数。

英文:

You can't define methods inside a function, for details see https://stackoverflow.com/questions/28252117/golang-nested-class-inside-function/28252170#28252170.

What you may do is create an implementation of SObject which is capable of dispatching to custom functions in its own implementation. An easy way to create such "proxy" implementation is to use a struct with fields of function types matching the types of the methods (without a receiver), and implement methods on this struct. The method implementations may simply forward the calls to the function values stored in the struct fields, and may have a default behavior if the appropriate field is not set. And you may change the values of the function fields, the behavior of the methods will be dynamic.

Here's an example of it:

type sobjimpl struct {
	apiName           func() string
	externalIdApiName func() string
}

func (s *sobjimpl) ApiName() string {
	if s.apiName == nil {
		return &quot;&lt;not implemented&gt;&quot;
	}
	return s.apiName()
}

func (s *sobjimpl) ExternalIdApiName() string {
	if s.externalIdApiName == nil {
		return &quot;&lt;not implemented&gt;&quot;
	}
	return s.externalIdApiName()

}

func createApiNameMethod(name string) SObject {
	return &amp;sobjimpl{
		apiName: func() string { return name },
	}
}

Testing it:

so := createApiNameMethod(&quot;testName&quot;)
fmt.Println(so.ApiName())

Output is as expected (try it on the Go Playground):

testName

Of course in this simple example the sobjimpl.apiName function field could be left out entirely, it could have been enough to just store the name and return that from sobjimpl.ApiName(). But the example shows how you may choose functions at runtime that will be called as the methods of an implementation.

huangapple
  • 本文由 发表于 2017年9月7日 21:52:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/46098189.html
匿名

发表评论

匿名网友

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

确定