The following code works fine. Two methods operating on two different structs and printing a field of the struct:
type A struct {
Name string
}
type B struct {
Name string
}
func (a *A) Print() {
fmt.Println(a.Name)
}
func (b *B) Print() {
fmt.Println(b.Name)
}
func main() {
a := &A{"A"}
b := &B{"B"}
a.Print()
b.Print()
}
Shows the desired output in the console:
A
B
Now, if I change the method signature in the following way I get an compile error. I just move the receiver of the method to the arguments of the method:
func Print(a *A) {
fmt.Println(a.Name)
}
func Print(b *B) {
fmt.Println(b.Name)
}
func main() {
a := &A{"A"}
b := &B{"B"}
Print(a)
Print(b)
}
I can't even compile the program:
./test.go:22: Print redeclared in this block
previous declaration at ./test.go:18
./test.go:40: cannot use a (type *A) as type *B in function argument
Question: Why is it, that I can interchange struct types in the receiver, but not in the arguments, when the methods have the same name and arity?
Because Go does not support overloading of user-defined functions on their argument types.
You can make functions with different names instead, or use methods if you want to "overload" on only one parameter (the receiver).
You can use type introspection. As a general rule, though, any use of the generic
interface{}
type should be avoided, unless you are writing a large generic framework.That said, a couple of ways to skin the proverbial cat:
Both methods assume a Print() method is defined for both types (
*A
and*B
)Method 1:
Method 2:
If it's undesirable to have a
Print()
method for each type, define targetedPrintA(*A)
andPrintB(*B)
functions and alter Method 1 like so:Working playground example here.