函数指针作为带有“返回接口{}”的参数

时间:2019-12-18 17:57:17

标签: go function-pointers

我想将指向函数的函数指针传递给“任何东西”。

很容易打印从几乎所有内容中传入的内容(如https://play.golang.org/p/gmOy6JWxGm0):

func printStuff(stuff interface{}) {
    fmt.Printf("Testing : %v", stuff)
}

不过,我要说的是:

  1. 具有多个结构
  2. 具有从各种功能加载的数据
  3. 具有可为我调用该函数的通用打印

我在Play(https://play.golang.org/p/l3-OkL6tsMW)中尝试过此操作,但遇到以下错误:

  

./ prog.go:35:12:在printStuff的参数中不能使用getStuff1(类型func()SomeObject)作为FuncType类型

     

./ prog.go:36:12:不能在printStuff的参数中使用getStuff2(类型func()SomeOtherObject)作为FuncType类型

万一Play内容被删除,这是我试图弄清楚如何工作的代码:

package main

import (
    "fmt"
)

type SomeObject struct {
    Value string
}

type SomeOtherObject struct {
        Value string
}

type FuncType func() interface{}

func getStuff1() SomeObject {
    return SomeObject{
        Value: "Hello, world!",
    }
}

func getStuff2() SomeOtherObject {
    return SomeOtherObject{
        Value: "Another, hello!",
    }
}

func printStuff(toCall FuncType) {
    stuff := toCall()
    fmt.Printf("Testing : %v", stuff)
}

func main() {
    printStuff(getStuff1)
    printStuff(getStuff2)
}

正确传递这些东西的秘诀是什么?

大目标说明

所以我要在这里完成的工作是减少巨大文件中的样板代码。不幸的是,由于其他限制,我现在无法进一步重构它,我想知道考虑错误消息是否完全可行,而我所读的内容似乎另有规定。

有大量的复制粘贴代码,如下所示:

func resendContraDevice(trap *TrapLapse, operation *TrapOperation) {
    loaded := contra.Load()
    err := trap.SnapBack(operation).send(loaded);

    // default error handling
    // logging
    // boilerplate post-process
}

func resendPolicyDevice(trap *TrapLapse, operation *TrapOperation) {
    loaded := policy.Load()
    err := trap.SnapBack(operation).send(loaded);

    // default error handling
    // logging
    // boilerplate post-process
}

// etc.

在这些函数中,Load()函数都返回不同的结构类型,并且它们在整个应用程序中的其他位置使用。

我希望能得到一些我可以拥有的东西:

loaded := fn()
err := trap.SnapBack(operation).send(loaded);

// default error handling
// logging
// boilerplate post-process

发送的签名是,它接受一个interface{}参数:

func (s SnapBack) send(data interface{}) error

1 个答案:

答案 0 :(得分:0)

例如,我不知道您是否可以控制contra.Load()policy.Load()的返回值,因此可能有更好的方法,但是假设不能修改这些返回值,则可以您无需进行任何花哨的操作即可消除很多样板:

func boilerplate(tram *TrapLapse, operation *TrapOperation, loader func() interface{}) {
    loaded := loader()
    err := trap.SnapBack(operation).send(loaded);

    // default error handling
    // logging
    // boilerplate post-process
}

func resendContraDevice(trap *TrapLapse, operation *TrapOperation) {
    boilerplate(trap, operation, func() interface{} { return contra.Load() })
}

func resendPolicyDevice(trap *TrapLapse, operation *TrapOperation) {
    boilerplate(trap, operation, func() interface{} { return policy.Load() })
}

如果没有什么更复杂的了,您还可以进一步简化:

func boilerplate(tram *TrapLapse, operation *TrapOperation, loaded interface{}) {
    err := trap.SnapBack(operation).send(loaded);

    // default error handling
    // logging
    // boilerplate post-process
}

func resendContraDevice(trap *TrapLapse, operation *TrapOperation) {
    boilerplate(trap, operation, contra.Load())
}

func resendPolicyDevice(trap *TrapLapse, operation *TrapOperation) {
    boilerplate(trap, operation, policy.Load())
}