doudao8283
2017-09-07 13:52 阅读 58
已采纳

从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) <return type> {
    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条回答 默认 最新

  • 已采纳
    dongpo8702 dongpo8702 2017-09-07 14:20

    You can't define methods inside a function, for details see Golang nested class inside function.

    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 "<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 },
        }
    }
    

    Testing it:

    so := createApiNameMethod("testName")
    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.

    点赞 评论 复制链接分享

相关推荐