43

If I have:

   type foo struct{
   }

   func bar(baz interface{}) {
   }

The above are set in stone - I can't change foo or bar. Additionally, baz must converted back to a foo struct pointer inside bar. How do I cast &foo{} to interface{} so I can use it as a parameter when calling bar?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
lf215
  • 1,185
  • 7
  • 41
  • 83

4 Answers4

78

To turn *foo into an interface{} is trivial:

f := &foo{}
bar(f) // every type implements interface{}. Nothing special required

In order to get back to a *foo, you can either do a type assertion:

func bar(baz interface{}) {
    f, ok := baz.(*foo)
    if !ok {
        // baz was not of type *foo. The assertion failed
    }

    // f is of type *foo
}

Or a type switch (similar, but useful if baz can be multiple types):

func bar(baz interface{}) {
    switch f := baz.(type) {
    case *foo: // f is of type *foo
    default: // f is some other type
    }
}
ANisus
  • 74,460
  • 29
  • 162
  • 158
  • What about if you dont know the type of interface? `baz` in your example – Juan de Parras Feb 28 '15 at 18:28
  • 7
    @JuandeParras: If you don't know what kind of types `baz` might be, then you will have to work with reflection (`import "reflect"`). This is how packages like `encoding/json` can encode basically any type without knowing before hand. – ANisus Mar 01 '15 at 16:14
  • Is there a way to do this with slices? – jocull Jul 08 '15 at 22:33
  • i dont get this. you are sending an object with address of struct foo but in the function it accepts an interface? when I try this and print the type using fmt.Printf it says the type is a struct pointer, not interface .... – Saim Mahmood Aug 30 '19 at 05:34
  • 1
    @SaimMahmood `fmt.Printf` will always receive its arguments as interfaces. What it does is telling you the type _inside_ the interface. That means that `fmt.Printf("%T", f)` and `fmt.Printf("%T", interface{}(f))` is the same. The only difference is that in the latter, I did a redundant explicit conversion. – ANisus Aug 30 '19 at 06:29
6

use reflect

reflect.ValueOf(myStruct).Interface().(newType)
archever
  • 77
  • 1
  • 2
  • 4
    `reflect` can do this, but it's a heavy and dangerous way of conversion. There is a much easier way, described in accepted answer. – alexykot Mar 20 '20 at 08:02
1

Converting a struct to interface can be achieved like this. Where i is an assign data structure.

var j interface{} = &i

PodTech.io
  • 4,874
  • 41
  • 24
  • This is should be the right answer, so from the question it can be something like this: var newFoo interface{} = &foo{} bar(newFoo) – tyohan Mar 15 '23 at 09:41
0

Not fully-related, but I googled the question "convert interface struct to pointer" and get here.

So, just make a note: to convert an interface of T to interface of *T:

//
// Return a pointer to the supplied struct via interface{}
//
func to_struct_ptr(obj interface{}) interface{} {
    vp := reflect.New(reflect.TypeOf(obj))
    vp.Elem().Set(reflect.ValueOf(obj))
    return vp.Interface()
}
shawn
  • 4,305
  • 1
  • 17
  • 25