3

So I'm basically trying to find out the best way to get to something like this:

package main

import "fmt"

type SomeStruct struct {
}

type SomeInterface interface {
  SomeMethodWhichNeedsAPointerReceiver() string
}

func (s *SomeStruct) SomeMethodWhichNeedsAPointerReceiver() string {
  return "Well, believe me, I wrote something"
}

func Run(s interface{}) {
  // how can I cast s to a pointer here?
  casted, ok := (s).(SomeInterface)
  if ok {
    fmt.Println("Awesome: " + casted.SomeMethodWhichNeedsAPointerReceiver())
    return 
  }

  fmt.Println("Fail :(")
}

func SomeThirdPartyMethod() interface{} {
  return SomeStruct{}
}

func main() {
  x := SomeThirdPartyMethod()
  Run(x)
}

My problem here is, at the typecast in the Run method. I basically only know that it is of type interface{} and now I need to call an interface method, which has a pointer receiver.

My only solution at the moment is to dynamically construct a slice with reflection, set the element into the slice, and than make it adressable.

Is this really the only possibility to find a solution?

Play link

3
  • well not really, since I actually want a solution without reflection. But yeah, if it isn't possible, it might be a duplicate. Commented Apr 20, 2015 at 10:55
  • For me, I don't like third_party_libs which have funcs returning interface{}. To my mind it's untyped, hard to understand and use, bad practice. I'd just avoid to use such a lib. I much prefer SomeThirdPartyMethod() which returns something explicitly - say SomeStruct, or SomeInterface, but not interface{} Commented Apr 20, 2015 at 11:59
  • it would be the same if the return type would be of an interface lets say... InterfaceA und it optionally may implemented interfaceB. Commented Apr 22, 2015 at 9:40

2 Answers 2

6

In Go, an interface is just a set of methods (spec: Interface types).

The interface does not specify whether receivers are pointers or not. Implementing an interface in Go is implicit: there is no declaration of intent.

You need to read and understand Method sets. Quoting an important part of it:

The method set of any other type T consists of all methods declared with receiver type T. The method set of the corresponding pointer type *T is the set of all methods declared with receiver *T or T (that is, it also contains the method set of T).

A value (which may or may not be a pointer) implements an interface if the method set of its type is a superset of the interface (the methods of the interface type).

In your example:

func (s *SomeStruct) SomeMethodWhichNeedsAPointerReceiver() string{}

SomeMethodWhichNeedsAPointerReceiver() has a pointer receiver, so a value of type SomeStruct will not have this method, but a value of type *SomeStruct will.

So as a consequence a value of type SomeStruct does not implement your SomeInterface interface (because it does not have a SomeMethodWhichNeedsAPointerReceiver() method), but *SomeStruct does implement your SomeInterface because its method set contains the SomeMethodWhichNeedsAPointerReceiver() method.

Since you create and use a simple SomeStruct value (and not a pointer to it), the type assertion will fail.

Should you have used a *SomeStruct, the type assertion would have succeeded.

Modify your SomeThirdPartyMethod() function to create and return a *SomeStruct (a pointer) and it will work as you expect it:

func SomeThirdPartyMethod() interface{} {
    return &SomeStruct{}
}

Or as an alternative:

func SomeThirdPartyMethod() interface{} {
    return new(SomeStruct)
}

Try it on the Go Playground.

If you can't modify SomeThirdPartyMethod()

If you can't modify the SomeThirdPartyMethod() function: first of all, is it intended/required that it returns a value which implements SomeStruct? If so, then its current implementation is wrong, and you can expect it to return a value which does implement SomeStruct without you having to dereference it (in order to gain a value which implements SomeStruct).

In this specific case you can also try type assertion for SomeStruct itself:

if ss, ok := s.(SomeStruct); ok {
    fmt.Println(ss.SomeMethodWhichNeedsAPointerReceiver())
}

Calling ss.SomeMethodWhichNeedsAPointerReceiver() will automatically dereference ss to take its address (which will be the pointer receiver value for calling the SomeMethodWhichNeedsAPointerReceiver() method).

Sign up to request clarification or add additional context in comments.

1 Comment

well, the third party method specifies the interface as optional. So therefore it must not be implemented, and the return value is interface{}. It's not elegant, but that's how it is.
4

The best solution would indeed be to return a pointer from SomeThirdPartyMethod. But if this is not possible, you can construct a pointer to that value using reflection:

v := reflect.Indirect(reflect.New(reflect.TypeOf(s)))
v.Set(reflect.ValueOf(s))
sp := v.Addr().Interface()
casted, ok = (sp).(SomeInterface)
if ok {
    fmt.Println("Good as well: " + casted.SomeMethodWhichNeedsAPointerReceiver())
    return
}

Working example: http://play.golang.org/p/JYJT8mRxWN

1 Comment

Yeah that is the only way we found as well. I upvoted you're answer but I will let this question open for now to find other suggestions. But thx for your response for now :D

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.