How to cast *interface{} into *T ?

1,365 views
Skip to first unread message

Denis P

unread,
Nov 24, 2022, 5:16:03 PM11/24/22
to golang-nuts
Hi guys, tried to look everywhere and cannot find an answer.

So literally I have this:
```
var result interface{} = &MyStruct{}

...

return result.(*MyStruct) // Error:  invalid operation: result (variable of type *interface{}) is not an interface
```

Is there any way to get the &MyStruct as a result?

Axel Wagner

unread,
Nov 24, 2022, 5:29:21 PM11/24/22
to Denis P, golang-nuts
Hi,


On Thu, Nov 24, 2022 at 11:16 PM Denis P <denis....@gmail.com> wrote:
Hi guys, tried to look everywhere and cannot find an answer.

So literally I have this:
```
var result interface{} = &MyStruct{}

...

return result.(*MyStruct) // Error:  invalid operation: result (variable of type *interface{}) is not an interface
```

No, offense, but you literally do not have that code, because the error message does not fit that code. In your code, `result` has type `interface{}`, whereas in the `return` statement, according to the error message, it has type `*interface{}`. Ergo, you are either shadowing `result` in-between, or the code is not equivalent.

In any case, the immediate solution could be to dereference the pointer:
return (*result).(*MyStruct)
 

Is there any way to get the &MyStruct as a result?

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/25da3c8f-6126-439a-904a-5fec59cb09f4n%40googlegroups.com.

Denis P

unread,
Nov 24, 2022, 6:14:27 PM11/24/22
to golang-nuts
Ok, looks like it doesn't work.

I have got the following error:
panic: interface conversion: interface {} is MyStruct, not *MyStruct

So the actual code is this: https://go.dev/play/p/jBiPII7rOxG

Cannot find out what is going on :-(

Denis P

unread,
Nov 24, 2022, 6:33:47 PM11/24/22
to golang-nuts

Thanks everyone, especially Axel

Denis P

unread,
Nov 24, 2022, 6:57:09 PM11/24/22
to golang-nuts
Still bad solution.

Because I am dereferencing the struct it clones the instance, and it what I am trying to avoid:

Any other solutions?

Axel Wagner

unread,
Nov 25, 2022, 1:12:24 AM11/25/22
to Denis P, golang-nuts
On Fri, Nov 25, 2022 at 12:14 AM Denis P <denis....@gmail.com> wrote:
Ok, looks like it doesn't work.

I have got the following error:
panic: interface conversion: interface {} is MyStruct, not *MyStruct

So the actual code is this: https://go.dev/play/p/jBiPII7rOxG

Cannot find out what is going on :-(

The runtime is telling you - the dynamic type of the interface is not `MyStruct`, it is `*MyStruct`:

 w := &MyWrapper{Obj: MyStruct{}}

Here, you are putting a `MyStruct` into `w.Obj`.

 s := GetOf[MyStruct](&w.Obj)

You are calling `GetOf` with the address of `w.Obj`. That is, you are passing an `*interface{}` to `GetOf[MyStruct]`. That `*interface{}` points at an interface containing a `MyStruct` (as you just put that in).

func GetOf[T interface{}](obj *interface{}) *T {
    return (*obj).(*T)
}

After instantiation, you are type-asserting the pointee of the passed pointer to `*MyStruct`. But the value in there is a `MyStruct`. So this panics.

I don't know how to fix your code, because I do not understand what you are trying to do. One way to make the panic go away is to put a `*MyStruct` into `w.Obj`:

 w := &MyWrapper{Obj: &MyStruct{}}

(note the second `&`). Another would be, to not type-assert on a `*T`, but a `T` and return a pointer pointing at the same value:

x := (*obj).(T)
return &x

You also probably do not want to take a `*interface{}`, but just take the interface directly… So maybe you want this? https://go.dev/play/p/5w-sMtVyTE3

The code isn't particularly functional, so I have no idea what the intended fix is. But the compiler and runtime are telling you, what you are doing wrong, in either case.
 

On Thursday, 24 November 2022 at 22:29:21 UTC axel.wa...@googlemail.com wrote:
Hi,


On Thu, Nov 24, 2022 at 11:16 PM Denis P <denis....@gmail.com> wrote:
Hi guys, tried to look everywhere and cannot find an answer.

So literally I have this:
```
var result interface{} = &MyStruct{}

...

return result.(*MyStruct) // Error:  invalid operation: result (variable of type *interface{}) is not an interface
```

No, offense, but you literally do not have that code, because the error message does not fit that code. In your code, `result` has type `interface{}`, whereas in the `return` statement, according to the error message, it has type `*interface{}`. Ergo, you are either shadowing `result` in-between, or the code is not equivalent.

In any case, the immediate solution could be to dereference the pointer:
return (*result).(*MyStruct)
 

Is there any way to get the &MyStruct as a result?

--
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.
To view this discussion on the web visit https://groups.google.com/d/msgid/golang-nuts/25da3c8f-6126-439a-904a-5fec59cb09f4n%40googlegroups.com.

--
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.

Axel Wagner

unread,
Nov 25, 2022, 1:25:23 AM11/25/22
to Denis P, golang-nuts
To be clear what I mean with "not particularly functional": Your GetOf is just doing a type-assertion, so the right way to write it would be this: https://go.dev/play/p/hTqOCbc07-K
You must have a reason to go through the more complicated dance of your GetOf function, but without knowing that, it's hard to tell what exactly the misunderstanding or the best solution is.

Nigel Tao

unread,
Nov 25, 2022, 2:40:59 AM11/25/22
to Axel Wagner, Denis P, golang-nuts

Brian Candler

unread,
Nov 25, 2022, 3:19:17 AM11/25/22
to golang-nuts
To give a real-world example:


type metrics struct {
        cpuTemp    prometheus.Gauge
        hdFailures *prometheus.CounterVec
}

Question: why is prometheus.Gauge not a pointer, but *prometheus.CounterVec is a pointer?

Answer: because prometheus.Gauge is an interface, whereas prometheus.CounterVec is a struct.

An interface essentially already *contains* a pointer to a data value - in fact, a tuple of (type, pointer).  So you should never take a pointer to an interface.  Just pass the interface value, and it will copy the (type, pointer) pair.

However, when you extract a value from an interface, it *will* always copy the internal value.  This avoids aliasing issues: someone who passes an interface value to someone else, won't expect the recipient to be able to change the sender's copy.

e.g.

Of course, if your interface *contains* a pointer, then the recipient of the interface can modify the thing being pointed to.

But they can't modify the pointer itself held within the interface, to make it point to something else.

The short version is: avoid pointers to interfaces, as the FAQ says.  Instead, let a concrete pointer value satisfy an interface.

On Friday, 25 November 2022 at 07:40:59 UTC Nigel Tao wrote:

Denis P

unread,
Nov 25, 2022, 4:55:10 AM11/25/22
to golang-nuts
Thank you everyone for your help.
The problem still exists.
I am looking for a solution where s and s2 point to the same instance.
The current example proves they are different instances.

The main goal is to store any type in a wrapper and then get the reference of the actual struct.
Also it must be the same instance, so the println should print 2, 2, 2

But look like there is no obvious solution. :-(

Martin Schnabel

unread,
Nov 25, 2022, 5:05:21 AM11/25/22
to Denis P, golang-nuts


On 11/25/22 10:55, Denis P wrote:
> Thank you everyone for your help.
> The problem still exists.
> I am looking for a solution where s and s2 point to the same instance.
> The current example proves they are different instances.
> https://go.dev/play/p/_JyfJelhIy4
>
> The main goal is to store any type in a wrapper and then get the
> reference of the actual struct.
> Also it must be the same instance, so the println should print 2, 2, 2
>
> But look like there is no obvious solution. :-(

There were only a couple of small mistakes. Hope an example clears it up.

https://go.dev/play/p/VhKIokDPCdq

Axel Wagner

unread,
Nov 25, 2022, 5:09:07 AM11/25/22
to Denis P, golang-nuts
If you assign a value to an interface, it will get copied. That's the same as if you assign an int to another int - it will get copied. If you want the interface to contain a reference, you have to assign a pointer to it: https://go.dev/play/p/nLw51pjWh4u

Side note: Go doesn't have "instances". It has "variables", which is probably what you mean.

--
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.

Denis P

unread,
Nov 25, 2022, 8:54:04 AM11/25/22
to golang-nuts
Thanks everyone. :-)

The problem solved. Yay

oh-yay.gif

Deeptiman Pattnaik

unread,
Nov 25, 2022, 11:35:50 AM11/25/22
to Axel Wagner, Denis P, golang-nuts
If you create a wrapper interface type and create generic constraints with the MyWrapper struct then it'll type cast with interface with (T).





--
    

Thanks & Regards
Deeptiman Pattnaik

Denis P

unread,
Nov 28, 2022, 11:00:57 AM11/28/22
to golang-nuts
Thanks guys. I have finished my homework thanks to you: https://pkg.go.dev/github.com/fairking/di_plus
Reply all
Reply to author
Forward
0 new messages