I have tried the following to update an empty map declared as a struct field:
package main
type MyStruct struct {
scoreboard map[string]int
}
func main() {
mystruct := NewMyStruct()
mystruct.SubmitWord('test')
}
func NewMyStruct() MyStruct {
return MyStruct{}
}
func (mystruct *MyStruct) SubmitWord(word string) int {
mystruct.scoreboard[word] = len(word)
return len(word)
}
but I get an error with exit status 2.
The problematic line being mystruct.scoreboard[word] = len(word)
Anything I can find seems to suggest this is ok but I haven't found any other examples where the map is within a struct.
you need to allocate the map first
package main
type MyStruct struct {
scoreboard map[string]int
}
func main() {
mystruct := NewMyStruct()
mystruct.SubmitWord("test")
}
func NewMyStruct() MyStruct {
var x MyStruct
x.scoreboard=make(map[string]int)
return x
}
func (mystruct *MyStruct) SubmitWord(word string) int {
mystruct.scoreboard[word] = len(word)
return len(word)
}
playground : https://play.golang.org/p/ipqHJ8TdUfh
Related
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)
}
I am trying to imitate what is happening in error in a similar piece of code, first piece of code prints --- log second does not why? or in other words I am trying to understand how Error() method got called without explicitly calling.
package main
import (
"fmt"
)
type argError struct {
arg int
prob string
}
func (e *argError) Error() string {
return fmt.Sprintf("%d ---- %s", e.arg, e.prob)
}
func f2(arg int) (int, error) {
return -1, &argError{arg, "can't work with it"}
}
func main() {
a,b := f2(42)
fmt.Println(a)
fmt.Println(b)
}
package main
import (
"fmt"
)
type myerr interface {
Apple() string
}
type dummy struct {
age int
name string
}
func (d *dummy) Apple() string {
return fmt.Sprintf("%d --- %s", d.age, d.name)
}
func f1(arg int) (string, myerr) {
return "f1", &dummy{arg, "ret"}
}
func main() {
i, j := f1(42)
fmt.Println(i)
fmt.Println(j)
}
To make it work, your type has to implement the error interface by having a Error method. I recommend adjusting your myerr interface to embed error, like so:
package main
import (
"fmt"
)
type myerr interface {
error // <--- note: embedding 'error' here
Apple() string
}
type dummy struct {
age int
name string
}
func (d *dummy) Apple() string {
return fmt.Sprintf("%d --- %s", d.age, d.name)
}
// <--- note: implement the 'error' interface for the 'dummy' type
func (d *dummy) Error() string {
return fmt.Sprintf("%d ---- %s", d.age, d.name)
}
func f1(arg int) (string, myerr) {
return "f1", &dummy{arg, "ret"}
}
func main() {
i, j := f1(42)
fmt.Println(i)
fmt.Println(j)
}
This should invoke the Error method of j as you'd expect.
You can try it on the Go playground.
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
I am trying to get embedded type from Go structs. Below is an example program that demonstrates this. Is there a way to write myfunc() without enumerating every type that can come in as input?
https://play.golang.org/p/5wp14O660m
package main
import (
"fmt"
)
type ObjectMeta struct {
Name string
Namespace string
}
type A struct {
ObjectMeta
X string
}
type B struct {
ObjectMeta
X string
}
func myfunc(v interface{}) ObjectMeta {
switch u := v.(type) {
case *A:
return u.ObjectMeta
case A:
return u.ObjectMeta
case *B:
return u.ObjectMeta
case B:
return u.ObjectMeta
}
panic("No matching type")
}
func main() {
fmt.Println(myfunc(&A{}))
var v interface{} = &A{}
fmt.Println(v.(*ObjectMeta))
}
ObjectMeta, A, B structs exist in external project. I have no control over them.
It can be done using reflection, iterating through the fields of the incoming value:
func myfunc(v interface{}) ObjectMeta {
// Elem() to de-reference pointer
ifv := reflect.ValueOf(v).Elem()
ift := reflect.TypeOf(v).Elem()
for i := 0; i < ift.NumField(); i++ {
f := ift.Field(i)
if f.Name == "ObjectMeta" {
fv := ifv.Field(i)
return fv.Interface().(ObjectMeta)
}
}
panic("ObjectMeta not found")
}
Playground: https://play.golang.org/p/CzMHJWhxYr
You can define interface which will get you that embedded type:
package main
import (
"fmt"
)
type HasMeta interface {
GetMeta() ObjectMeta
}
type ObjectMeta struct {
Name string
Namespace string
}
func (o ObjectMeta) GetMeta() ObjectMeta {
return o
}
type A struct {
ObjectMeta
X string
}
type B struct {
ObjectMeta
X string
}
func myfunc(o HasMeta) ObjectMeta {
return o.GetMeta()
}
func main() {
fmt.Println(myfunc(&A{}))
fmt.Println(myfunc(A{}))
fmt.Println(myfunc(&B{}))
fmt.Println(myfunc(B{}))
}
https://play.golang.org/p/CWa4k-kvvl
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)
}
}