How to set pointer value in go? - go

package main
import "fmt"
func doStuff(q interface{}) {
*q = MyStruct{2}
}
type MyStruct struct {
f1 int
}
func main() {
ms := MyStruct{1}
doStuff(&ms)
fmt.Printf("Hello, playground: %v\n", ms)
}
Is it possible to set ms through pointer q to have new value MyStruct{2}? I am getting this error invalid indirect of q (type interface {})

interface{} is not a pointer type. So, you cannot change it's underlying value.
Instead, you can modify q value and return it from the doStuff function if you really need to do so.
example:
package main
import "fmt"
func doStuff(q interface{}) interface{} {
q = &MyStruct{2}
return q
}
type MyStruct struct {
f1 int
}
func main() {
var ms interface{} = MyStruct{1}
ms = doStuff(&ms)
fmt.Printf("Hello, playground: %v\n", ms)
}

You can't using the interface{} type, since it's not a literal type you can memory address like you're attempting. An interface type describes general behavior, not a specific value.
If you use the MyStruct type directly, you can get a pointer and do what you want.
package main
import "fmt"
func doStuff(q *MyStruct) {
*q = MyStruct{2}
}
type MyStruct struct {
f1 int
}
func main() {
ms := MyStruct{1}
doStuff(&ms)
fmt.Printf("Hello, playground: %v\n", ms)
}
Go playground linke

Related

Simplify casting in Go when taking any interface as a parameter

I have a struct like so,
//
// HandlerInfo is used by features in order to register a gateway handler
type HandlerInfo struct {
Fn func(interface{})
FnName string
FnRm func()
}
where I want to pass a func:
func StarboardReactionHandler(e *gateway.MessageReactionAddEvent) {
// foo
}
i := HandlerInfo{Fn: StarboardReactionHandler}
Unfortunately, this results in:
Cannot use 'StarboardReactionHandler' (type func(e *gateway.MessageReactionAddEvent)) as the type func(interface{})
I found this workaround:
func StarboardReactionHandler(e *gateway.MessageReactionAddEvent) {
// foo
}
func handlerCast(e interface{}) {
StarboardReactionHandler(e.(*gateway.MessageReactionAddEvent))
}
i := HandlerInfo{Fn: handlerCast}
Is there some way that I can simplify needing handlerCast, such as doing it inside my StarboardReactionHandler or in HandlerInfo? Maybe with generics or reflection? I basically just want to minimize the syntax / boilerplate that's required here.
you can use interface{}.(type)
follow is a exmple:
package main
import "fmt"
type HandlerInfo struct {
Fn func(interface{})
FnName string
FnRm func()
}
type MessageReactionAddEvent = func(a, b int) int
func StarboardReactionHandler(e interface{}) {
switch e.(type) {
case MessageReactionAddEvent:
fmt.Printf("%v\n", (e.(MessageReactionAddEvent))(1, 2))
}
}
func add(a, b int) int {
return a + b
}
func main() {
i := HandlerInfo{Fn: StarboardReactionHandler}
i.Fn(add)
}

How to pass a pointer to a slice of a specific interface in Go?

I want to achieve polymorfism by passing a pointer to a slice of a speficic interface to a function, and update the slice inside of the function. It works quite well with interface{}
package main
import (
"fmt"
"strconv"
)
type valuer interface {
value() string
}
type myInt int
func (i myInt) value() string {
return strconv.Itoa(int(i))
}
func values(vals interface{}) {
res, ok := vals.(*[]myInt)
if !ok {
panic("wrong type")
}
*res = []myInt{1, 2, 3}
}
func main() {
var a []myInt
values(&a)
for _, b := range a {
fmt.Println(b.value())
}
}
Go Playground
However if I try to change interface{} to a pointer to a slice of a specific interface it does not work:
package main
import (
"fmt"
"strconv"
)
type valuer interface {
value() string
}
type myInt int
func (i myInt) value() string {
return strconv.Itoa(int(i))
}
func values(vals *[]valuer) {
*vals = []myInt{1, 2, 3}
}
func main() {
var a []myInt
values(&a)
for _, b := range a {
fmt.Println(b.value())
}
}
Go Playground
returning an error
./prog.go:19:8: cannot use []myInt literal (type []myInt) as type []valuer in assignment
./prog.go:24:9: cannot use &a (type *[]myInt) as type *[]valuer in argument to values
What am I doing wrong?
From the insights provided by #kostix, I can see that I cannot keep both -- a restriction of a non-empty interface, and a simplicity of passing a pointer of a slice of a concrete type. So if I do want to keep the output as a slice of non-empty interfaces, I can do something of this sort instead:
package main
import (
"fmt"
"strconv"
)
type valuer interface {
value() string
}
type myInt int
func (i myInt) value() string {
return strconv.Itoa(int(i))
}
func values() []valuer {
res := make([]valuer, 3)
c := []myInt{1, 2, 3}
for i, v := range c {
res[i] = v
}
return res
}
func main() {
a := values()
for _, b := range a {
fmt.Println(b.value())
}
}
Go Playground
It would keep api simpler to use, and allow polymorphism with non-empty interfaces for the output.
One inconvenience for the users with this approach, they will have to "unbox" members of the slice if they want to use methods of a concrete type that are not specified by the interface.

Can I convert *interface{} to *int using unsafe.Pointer in Go

I am making a memory pool in Go.
I am doing so because implicit converting int to interface{} will trigger a memory allocation.I want to avoid the allocation.
I want to allocate several types of pointers in one pool.
The pool is something like this.
type creator struct{
buf []interface{}
}
func (cr *creator) Create()*interface{}{
if len(cr.buf)==0{
cr.buf=make([]interface{},256)
}
current:=&cr.buf[0]
cr.buf=cr.buf[1:]
return current
}
func (cr *creator)CreateInt()*int{
pointer:=cr.Create()
return (*int)(unsafe.Pointer(pointer)) // <-- right or wrong?
}
Is the code valid?
You have *interface {} and you want to pretend that it is *int! How is that going to work?
package main
import (
"fmt"
"unsafe"
)
func main() {
var cr creator
pointer := cr.CreateInt()
fmt.Printf("%T\n", pointer) // *int
}
type creator struct {
buf []interface{}
}
func (cr *creator) Create() *interface{} {
if len(cr.buf) == 0 {
cr.buf = make([]interface{}, 256)
}
current := &cr.buf[0]
cr.buf = cr.buf[1:]
return current
}
func (cr *creator) CreateInt() *int {
pointer := cr.Create()
fmt.Printf("%T\n", pointer) // *interface {}
return (*int)(unsafe.Pointer(pointer)) // *interface {} to *int
}
Playground: https://play.golang.org/p/TLF7kbYPA0M
Output:
*interface {} 0x452000
*int 0x452000

Make an arbitrary slice type stringer method in Go

New to Golang. So I read about the stringer in the Go tour and I'm wondering is there any way to define a generic custom Stringer() for any type of slice? E.g.:
package main
import "fmt"
type IntSlice []int
func (a IntSlice) String() string {
return fmt.Sprintf("len %d\tcap %d", len(a), cap(a))
}
func main() {
a:=[40]int{}
sa:=IntSlice(a[:])
fmt.Println(unsafe.Sizeof(a), "\t", unsafe.Sizeof(sa), " ", cap(sa))
fmt.Println(sa)
}
Like this but without the type IntSlice definition.
Thanks!
type SliceStringer struct {
Slice interface{}
}
func (ss SliceStringer) String() string {
rv := reflect.ValueOf(ss.Slice)
return fmt.Sprintf("len %d\tcap %d", rv.Len(), rv.Cap())
}
https://play.golang.org/p/jWnm9vCDFhq

In go (golang), how can you cast an interface pointer into a struct pointer?

I want to use some external code that requires a pointer to a struct. At the point that the code is called, I have an interface variable.
When creating a pointer off of that variable, the pointer's type is interface{}* when I need it to be the pointer type of the struct's type.
Image the code in TestCanGetStructPointer does not know about the Cat class, and that it exists in some external package.
How can I cast it to this?
Here is a code sample:
import (
"reflect"
"testing"
)
type Cat struct {
name string
}
type SomethingGeneric struct {
getSomething func() interface{}
}
func getSomeCat() interface{} {
return Cat{}
}
var somethingForCats = SomethingGeneric{getSomething: getSomeCat}
func TestCanGetStructPointer(t *testing.T) {
interfaceVariable := somethingForCats.getSomething()
pointer := &interfaceVariable
interfaceVarType := reflect.TypeOf(interfaceVariable)
structPointerType := reflect.PtrTo(interfaceVarType)
pointerType := reflect.TypeOf(pointer)
if pointerType != structPointerType {
t.Errorf("Pointer type was %v but expected %v", pointerType, structPointerType)
}
}
The test fails with:
Pointer type was *interface {} but expected *parameterized.Cat
#dyoo's example does work, but it relies on you to manually cast Dog and Cat.
Here's a bit of a convoluted/verbose example which avoids that constraint somewhat:
package main
import (
"fmt"
"reflect"
)
type Cat struct {
name string
}
type SomethingGeneric struct {
getSomething func() interface{}
}
func getSomeCat() interface{} {
return Cat{name: "Fuzzy Wuzzy"}
}
var somethingForCats = SomethingGeneric{getSomething: getSomeCat}
func main() {
interfaceVariable := somethingForCats.getSomething()
castVar := reflect.ValueOf(interfaceVariable)
castVar.Convert(castVar.Type())
// If you want a pointer, do this:
fmt.Println(reflect.PtrTo(castVar.Type()))
// The deref'd val
if castVar.Type() != reflect.TypeOf(Cat{}) {
fmt.Printf("Type was %v but expected %v\n", castVar, reflect.TypeOf(&Cat{}))
} else {
fmt.Println(castVar.Field(0))
}
}
Playground Link
I found this thread: https://groups.google.com/forum/#!topic/golang-nuts/KB3_Yj3Ny4c
package main
import (
"fmt"
"reflect"
)
type Cat struct {
name string
}
//
// Return a pointer to the supplied struct via interface{}
//
func to_struct_ptr(obj interface{}) interface{} {
fmt.Println("obj is a", reflect.TypeOf(obj).Name())
// Create a new instance of the underlying type
vp := reflect.New(reflect.TypeOf(obj))
// Should be a *Cat and Cat respectively
fmt.Println("vp is", vp.Type(), " to a ", vp.Elem().Type())
vp.Elem().Set(reflect.ValueOf(obj))
// NOTE: `vp.Elem().Set(reflect.ValueOf(&obj).Elem())` does not work
// Return a `Cat` pointer to obj -- i.e. &obj.(*Cat)
return vp.Interface()
}
//
// Dump out a pointer ...
//
func test_ptr(ptr interface{}) {
v := reflect.ValueOf(ptr)
fmt.Println("ptr is a", v.Type(), "to a", reflect.Indirect(v).Type())
}
func main() {
cat := Cat{name: "Fuzzy Wuzzy"}
// Reports "*main.Cat"
test_ptr(&cat)
// Get a "*Cat" generically via interface{}
sp := to_struct_ptr(cat)
// *should* report "*main.Cat" also
test_ptr(sp)
fmt.Println("sp is",sp)
}
The following may help: http://play.golang.org/p/XkdzeizPpP
package main
import (
"fmt"
)
type Cat struct {
name string
}
type Dog struct {
name string
}
type SomethingGeneric struct {
getSomething func() interface{}
}
func getSomeCat() interface{} {
return Cat{name: "garfield"}
}
func getSomeDog() interface{} {
return Dog{name: "fido"}
}
var somethings = []SomethingGeneric{
SomethingGeneric{getSomething: getSomeCat},
SomethingGeneric{getSomething: getSomeDog},
}
func main() {
for _, something := range somethings {
interfaceVariable := something.getSomething()
cat, isCat := interfaceVariable.(Cat)
dog, isDog := interfaceVariable.(Dog)
fmt.Printf("cat %v %v\n", cat, isCat)
fmt.Printf("dog %v %v\n", dog, isDog)
}
}

Resources