Given the following struct Foo
and goal of handling multiple types (where Handle
could be Read
, Write
, etc.). I understand that we lose compile-time type checks when we use the empty interface, though aside from this, what are the pros and cons of each? Finally, what is the most idiomatic way to achieve this?
package main
type Foo struct {
A int
B string
}
//Handle all types with switch
func (f *Foo) Handle(obj interface{}) {
switch obj := obj.(type) {
case int:
//do int stuff...
f.A + obj
case string:
//do string stuff...
f.B + obj
default:
panic("Unknown type")
}
}
//Handle each type individually
func (f *Foo) HandleInt(i int) {
//do int stuff...
f.A + i
}
func (f *Foo) HandleString(s string) {
//do string stuff...
f.B + s
}
The empty interface is necessary if you're going to handle user-defined types via reflect
. That's fmt.Printf
, json.Encode
, and binary.Write
's reason for accepting it. In terms of the Merkle tree scenario you posted about earlier, where you're hashing things, you'd use an empty interface if your Hash()
had a reflect
-based fallback for hashing user-created structs.
Specific methods probably make more sense if you're only going to provide methods for a few key types ([]byte
, string
, whatever). Besides compile-time checking, the function list serves as documentation of what you can hash. On the other hand, if there are, like, a dozen-plus types you want to hash--think all the (u)int types and slices of them--I think I'd use an interface{}
just for the sake of an uncluttered API unless you absolutely needed the very best performance, but I don't think there's a clear consensus one way or the other.
One good example would be the package sort (sources here), which:
If you do the same for Handle(obj interface{})
=> Handle(obj Interface)
, that would help you handler (for more complex type) to be defined once, using the methods declared in 'Interface
'.
Any type satisfying said Interface
would be passed to the generic Handle()
function.
And you could Handle slice (similar to this example for sort
) or used-defined collection as well.