I'm writing a utility to import/export data into an API. I'd like to be able to accept multiple input/output formats, and support multiple commands. I was going to use kingpin for the flags/commands, and do a type format after that.
My plan was to declare an interface with the methods I'm going to use, a struct that's got the parameters needed for the interface, but doesn't satisfy it, and declare a map of structs that do satisfy that interface.
type versionParams struct {
options int
sess api.Session
in io.ReadCloser
out io.WriteCloser
log *log.Logger
}
type Version interface {
Import()
Export()
Example()
}
var versions map[string]Version
In main, I'd detect the actions, and if it's one of the actions for one of those types, create the object, load it up with input and output and stuff. Note, because of the flags I'm using, *format is a pointer to a string holding the format's name. So, I was thinking I'd do something like:
args := versionParams{}
// some stuff to fill in the args
args.(versions[*format]).Import()
Then, for each version I want to add, in that version I'd do something like the following, in it's own file:
type v1csv struct {
versionParams
Version
}
func init() {
versions["v1csv"] = v1csv
}
func (v *v1csv) Import() {
// do stuff
}
func (v *v1csv) Example() {
// do stuff
}
func (v *v1csv) Export() {
// do stuff
}
I don't think this works for multiple reasons though. I don't think you can declare a map of types that satisfy an interface like that? And once you do, I guess I don't know if I can cast/convert from one struct to another without directly naming the struct...? I guess I could drop the generic versionParams struct and just create structs for each type, but I would still want to put those struct types into a map - that's the part that I'm stuck on figuring out.
I wanted to go with something like this layout specifically so that I could add new formats by simply adding that one format in a self contained file. I don't want to statically name them and
Mostly, I think I'm just lost in design and I cannot see the way out myself. Any suggestions to help me figure out how to do this, or something more appropriate, would be appreciated. :-)