سؤال

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

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:

func Print(any interface{}) {
    switch v := any.(type) {
    case *A:
        v.Print()
    case *B:
        v.Print()
    default:
        fmt.Printf("Print() invoked with unsupported type: '%T' (expected *A or *B)\n", any)
        return
    }
}

Method 2:

type Printer interface {
    Print()
}

func Print(any interface{}) {
    // does the passed value honor the 'Printer' interface
    if v, ok := any.(Printer); ok {
        // yes - so Print()!
        v.Print()
    } else {
        fmt.Printf("value of type %T passed has no Print() method.\n", any)
        return
    }
}

If it's undesirable to have a Print() method for each type, define targeted PrintA(*A) and PrintB(*B) functions and alter Method 1 like so:

    case *A:
        PrintA(v)
    case *B:
        PrintB(v)

Working playground example here.

You can not do function or method overloading in Go. You can have two methods with the same names in Go but the receiver of these methods must be of different types. you can see more in this link .

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top