1

I am writing a home monitoring program that consist of plugins that are functions executing specific checks. Each plugin has a specific input (dependent on the nature of the check) and a response common to all plugins.

An example of the main types involved could be:

// PluginHTTPBasicStruct describes the configuration of a simple HTTP check (connection to a web server)
type PluginHTTPBasicStruct struct {
    Host          string
    ExpectedCodes []int
}

// PluginResponse describes the response of all plugins
type PluginResponse struct {
    OK   bool
    When time.Time
    Why  string
}

func PluginHTTPBasic(target PluginHTTPBasicStruct) PluginResponse {
  // checks happen here 
}

In that simple program, I would like to run a series of calls to a single runPlugin helper function, such as

runPlugin(PluginHTTPBasic, PluginHTTPBasicStruct{
        Host:          "one.example.com",
        ExpectedCodes: [200],
    })

Now, my goal is to have runPlugin take a first parameter which is a function, and a struct of any type (I will think about constraints later).

To this, I thought about using the following code:

// PluginInputsAll will list all possible inputs
type PluginInputsAll interface {
    PluginHTTPBasicStruct
}
type PluginFunction[T PluginInputsAll] func(T)
type PluginInput[T PluginInputsAll] T

func runPlugin(plugin PluginFunction, input PluginInput) {
    resp := plugin(input)
    log.Info().Msg(resp)
}

How can I structure such a generic function?

blackgreen
  • 34,072
  • 23
  • 111
  • 129
WoJ
  • 27,165
  • 48
  • 180
  • 345
  • 1
    as posed, this question is too broad, it reads like you are asking for a tutorial about generics. Have you tried compiling the code? Is there a particular error message you are confused about? – blackgreen May 20 '22 at 12:31
  • 1
    related readings: [how to write a generic function](https://stackoverflow.com/questions/42726986/generic-functions-in-go), [generic decorator](https://stackoverflow.com/questions/69759462/passing-an-arbitrary-function-as-a-parameter-in-go/69764684#69764684), [generic func as parameter](https://stackoverflow.com/questions/71861716/how-to-convert-from-func-int-to-func-interface?noredirect=1&lq=1) – blackgreen May 20 '22 at 12:34
  • @blackgreen: no, a tutorial maybe not - rather what to do with the code I posted (which is so wrong that it does not even makes sense to provide compiler errors - I was trying to show what kind of behaviour I was expecting). Your pointers are extremely useful, thank you very much!. If I manage to fix the code I will publish it as an answer. – WoJ May 20 '22 at 13:07
  • the starting point for the function signature should be smt like: `runPlugin[T any](plugin func(T) PluginResponse, input T)`, then add complexity when/if needed – blackgreen May 20 '22 at 13:12
  • @blackgreen: thank you very much - it works. I think I git the idea of `T` being defined in the brackets and then used in the definition. Would you be so kind and just copy your comment to an answer so that I can update it with working code? Thanks again! – WoJ May 20 '22 at 13:24
  • 1
    ehm, glad to have helped, but I'm more inclined to close as duplicate, since this question turns out to be in fact a duplicate :) – blackgreen May 20 '22 at 13:29

0 Answers0