I have a some structs like so:
type Datacenter struct {
Name string
Key string
Hosts []Host
}
type Host struct {
Name string
Port int
}
When these structs are populated, they look like this:
[]config.Datacenter (len=2) {
Datacenter {
Name: "dc1",
Key: "string",
Hosts: []config.Host (len=1) {
Host {
Name: "dc1-server-1",
Port: 8200 (int)
}
}
},
Datacenter {
Name: "dc2",
Key: "Another string",
Hosts: []config.Host (len=2) {
Host {
Name: "dc2-server-1",
Port: 8200 (int)
},
Host {
Name: "dc2-server-2",
Port: 8200 (int)
}
}
}
}
I am creating a CLI tool, and for almost every command, I range over these structs in this manner:
for _, d := range datacenters {
if datacenter == d.Name || datacenter == "" {
for _, h := range d.Hosts {
// do something on each host in the range here
}
}
}
Because I'm an awful, awful go developer, I know there is a better way to do this. The code is not very DRY at the moment, I am literally coping and pasting the range into each new subcommand, which looks awful and generally makes me feel stupid.
I think I need to creation a function and do the ranging inside that, and then decide on the return values. I just can't figure out what it should be, the concepts aren't there. Any help will be greatly appreciated.
It sounds like you want to do something like:
func EachHost(datacenter string, f func(Host)) {
for _, d := range datacenters {
if datacenter == d.Name || datacenter == "" {
for _, h := range d.Hosts {
// do something on each host in the range here
f(h)
}
}
}
}
And then you can do something like:
listHostNames := func(datacenter string) {
EachHost(datacenter, func(h Host) {
fmt.Println(h.Name)
});
}
listHostNames("dc1")