typecast reflected struct to interface

646 views
Skip to first unread message

epix...@gmail.com

unread,
Sep 12, 2015, 1:02:12 PM9/12/15
to golang-nuts
Hello, Trying to play with the reflect package and have some trouble casting the newly created struct into my "Entity" interface :

package main

import (
"reflect"
"fmt"
)

type Entity interface{
getElement() int32
}

type entityice struct {
elem int32
}

func (ice *entityice) getElement(){
return ice.elem
}

type entityfire struct {
elem int32
}

func (fire *entityfire) getElement(){
return fire.elem
}

var entityTypeRegistry = make(map[byte]reflect.Type)

func main() {
entityTypeRegistry[0] = reflect.TypeOf(entityice{0})
entityTypeRegistry[1] = reflect.TypeOf(entityfire{1})

entity := newEntity(0)
fmt.Println(entity.getElement())
}

func newEntity(entType int32) Entity{
reflection := reflect.New(entityTypeRegistry[entType]).Elem().Interface()
switch reflection.(type){
case entityice:
thevar := reflection.(entityice)
thevar.elem = 0
return &thevar
case entityfire:
thevar := reflection.(entityfire)
thevar.elem = 1
return &thevar
}
return nil
}

I can't find any way to not use an switch case for casting the reflected struct into my interface "Entity".

Ian Lance Taylor

unread,
Sep 12, 2015, 1:31:05 PM9/12/15
to epix...@gmail.com, golang-nuts
On Sat, Sep 12, 2015 at 4:43 AM, <epix...@gmail.com> wrote:
>
> I can't find any way to not use an switch case for casting the reflected
> struct into my interface "Entity".

Here's a tip: fmt.Printf("%T\n", reflection) will print the type of
the variable reflection. That may help show you what is going wrong.

Ian

epix...@gmail.com

unread,
Sep 12, 2015, 2:27:27 PM9/12/15
to golang-nuts, epix...@gmail.com
the main problem is the fact that the var "reflection" is actually a "interface{}" type, when I try to cast or return this as an "Entity", I get this error : 

.\main.go:46: cannot use reflection (type interface {}) as type Entity in return argument:
interface {} does not implement Entity (missing getElement method)

and I cannot type cast interface{} to entityice or entityfire dynamically without getting a build problem :

reflection := reflect.New(entityTypeRegistry[entType]).Elem().Interface()
entity := reflection.(entityTypeRegistry[entType])
return entity
Do not actually compile: 
.\main.go:2: entityTypeRegistry[entType] is not a type

Giulio Iotti

unread,
Sep 12, 2015, 3:35:03 PM9/12/15
to golang-nuts, epix...@gmail.com
On Saturday, September 12, 2015 at 9:27:27 PM UTC+3, epix...@gmail.com wrote:
and I cannot type cast interface{} to entityice or entityfire dynamically without getting a build problem :

reflection := reflect.New(entityTypeRegistry[entType]).Elem().Interface()
entity := reflection.(entityTypeRegistry[entType])
return entity
Do not actually compile: 
.\main.go:2: entityTypeRegistry[entType] is not a type

Yes, you cannot cast to a type that is not known at compile time.

If the list of types it could be cast to dynamically is know (for you it is entityfire and entityice), just use switch over entityTypeRegistry[entType].

-- 
Giulio Iotti

Ian Lance Taylor

unread,
Sep 12, 2015, 4:36:04 PM9/12/15
to epix...@gmail.com, golang-nuts


On Sep 12, 2015 11:27 AM, <epix...@gmail.com> wrote:
>
> the main problem is the fact that the var "reflection" is actually a "interface{}" type, when I try to cast or return this as an "Entity", I get this error : 
>
> .\main.go:46: cannot use reflection (type interface {}) as type Entity in return argument:
> interface {} does not implement Entity (missing getElement method)
>
> and I cannot type cast interface{} to entityice or entityfire dynamically without getting a build problem :
>
> reflection := reflect.New(entityTypeRegistry[entType]).Elem().Interface()
> entity := reflection.(entityTypeRegistry[entType])
> return entity
>
> Do not actually compile: 
> .\main.go:2: entityTypeRegistry[entType] is not a type

Define an interface type with the method you want, and convert to that.  If there is no common method, then I don't understand what you are trying to do.

Ian

> Le samedi 12 septembre 2015 19:31:05 UTC+2, Ian Lance Taylor a écrit :
>>
>> Here's a tip: fmt.Printf("%T\n", reflection) will print the type of
>> the variable reflection.  That may help show you what is going wrong.
>>
>> Ian
>

> --
> You received this message because you are subscribed to the Google Groups "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

epix...@gmail.com

unread,
Sep 12, 2015, 4:39:16 PM9/12/15
to golang-nuts, epix...@gmail.com
I don't really understand what you mean by using a switch over entityTypeRegistry[entType], (isn't that what i'm already doing on my first post ? )

also, what I'm sure is that every struct that is inside the entityTypeRegistry will implemente the interface Entity, isn't there anyway I could directly cast the "interface{}" to this "Entity" ? I have to manage a lot of different entity inside my program and doing a big long switch is really a bad scenario for me.

Ian Lance Taylor

unread,
Sep 12, 2015, 11:36:37 PM9/12/15
to epix...@gmail.com, golang-nuts
On Sat, Sep 12, 2015 at 1:39 PM, <epix...@gmail.com> wrote:
> I don't really understand what you mean by using a switch over
> entityTypeRegistry[entType], (isn't that what i'm already doing on my first
> post ? )

Yes, but you didn't show us what type the value had. Hence my
suggestion to print it with %T.

> also, what I'm sure is that every struct that is inside the
> entityTypeRegistry will implemente the interface Entity, isn't there anyway
> I could directly cast the "interface{}" to this "Entity" ? I have to manage
> a lot of different entity inside my program and doing a big long switch is
> really a bad scenario for me.

You can convert directly to Entity with a type assertion: v.(Entity).

Ian

epix...@gmail.com

unread,
Sep 13, 2015, 3:41:39 AM9/13/15
to golang-nuts, epix...@gmail.com


Le dimanche 13 septembre 2015 05:36:37 UTC+2, Ian Lance Taylor a écrit :
Yes, but you didn't show us what type the value had.  Hence my
suggestion to print it with %T.

sorry, I forget to answer that, the ouput was "main.entityfire" and "main.entityice", which was wrong because I was using "reflect.New(entityTypeRegistry[entType]).Elem().Interface()" instead of  "reflect.New(entityTypeRegistry[entType]).Interface()"  which gave me the correct output for typecast "*main.entityfire".

Le dimanche 13 septembre 2015 05:36:37 UTC+2, Ian Lance Taylor a écrit :
You can convert directly to Entity with a type assertion: v.(Entity). 

this actually resolved my problem ! thanks a lot, after rereading effective go, this was the first thing they show for interface ... shame on me for missing that spot.
Reply all
Reply to author
Forward
0 new messages