Golang interfaces & casting - go

I have the following code:
func returnTheMap() map[string][]string{
myThing := getSomeValue()
}
getSomeValue() returns something of type map[string]interface{}
but it is always internally a map[string][]string.
What is the best way to set myThing equal to the same thing as getSomeValue(), but of type map[string][]string?
I can make a new object like so:
newMap := make(map[string][]string)
// cardTypeList is of type map[string]interface {}, must convert to map[string][]string
for k, v := range myThing {
newMap[k] = v.([]string)
}
but is there any way to do this in-place, or is there any preferred way to do this?

According to Go FAQ, you cannot change the type of slice directly.
So it seems that your solution is the preferred way.

Is getSomeValue() your function? If so, I would change the return type to be map[string][]string rather than map[string][]interface.
If that is not the case, I would create some helpers to go through and check to make sure the types are set to your needs. I have an example in the playground
https://play.golang.org/p/9OPgXGXADY

Related

Function that returns Slice of Custom Interface

At first, I want to introduce you because I feel like I am missing some core Golang concept.
In my application, many models will have a method called GetByUserId. I created interface(UserCreatedEntity) that requires this method so then I will be able to create Controller's GetUserRecords method factory for each type of records with just:
router.Handle("/ideas/mine",
middlewares.AuthUser(controllers.GetMineFactory(&models.Idea{}))).Methods("POST")
router.Handle("/votes/mine",
middlewares.AuthUser(controllers.GetMineFactory(&models.Vote{}))).Methods("POST")
router.Handle("/someNewType/mine",
middlewares.AuthUser(controllers.GetMineFactory(&models.SomeNewType{}))).Methods("POST")
This is how my interface looks like:
type UserCreatedEntity interface {
GetByUserId(userId uint) []UserCreatedEntity
}
And implementation:
func (idea *Idea) GetByUserId(userId uint) []UserCreatedEntity {
ideas := []Idea{}
GetDB().
Table("ideas").
/** Query removed to make code less confusing **/
Scan(ideas)
return ideas
}
Obviously, it does not work (version with slice of pointers neither do). The thing is - This code would work if I return only one record - like that (obviously with changing signature in interface also):
func (idea *Idea) GetByUserId(userId uint) UserCreatedEntity {
idea := &Idea{}
GetDB().
Table("ideas").
/** Query removed to make code less confusing **/
First(idea)
return idea
}
How to make it work as slice? As I said I suspect that I am missing some important knowledge. So deep explaination would be awesome.
Solution:
func (idea *Idea) GetByUserId(userId uint) []UserCreatedEntity {
ideas := []*Idea{}
GetDB().
Table("ideas").
Select("problems.name AS problem_name, ideas.id, ideas.problem_id, ideas.action_description, ideas.results_description, ideas.money_price, ideas.time_price, ideas.is_published").
Joins("INNER JOIN problems ON ideas.problem_id = problems.id").
Where("ideas.user_id = ?", userId).
Scan(&ideas)
uces := make([]UserCreatedEntity, len(ideas))
for i, idea := range ideas {
uces[i] = idea
}
return uces
}
In programming language theory this is called variance, and it is not supported in Go. For much more details see this proposal.
Specifically, return types are not covariant. A slice of T does not implement a slice of I even if T implements I.
The FAQ entry linked above proposes this workaround:
It is necessary to copy the elements individually to the destination
slice. This example converts a slice of int to a slice of interface{}:
t := []int{1, 2, 3, 4}
s := make([]interface{}, len(t))
for i, v := range t {
s[i] = v
}
Though in your case the right solution may be different.
Interfaces are dynamic. Composite types that involve interfaces are not.
UserCreatedEntity is an interface, and Idea satisfies the interface, so you can return an Idea from a function whose signature has a return type of UserCreatedEntity.
[]UserCreatedEntity is a slice of UserCreatedEntity, not an interface. The only type that can be returned is []UserCreatedEntity. []Idea is a different type (slice of Idea). You can fill a []UserCreatedEntity with Idea elements, because each element is of type UserCreatedEntity, which again is an interface and Idea is allowed there.
Similarly, func() UserCreatedEntity is a type "function which returns UserCreatedEntity". You cannot subsitute a func() Idea because that is a different type. But you can return an Idea from a func() UserCreatedEntity because an Idea is a UserCreatedEntity.
If you weren't using Scan here, which presumably uses reflection, the fix would be to declare your local slice as []UserCreatedEntity instead of []Idea. Since you are using Scan, you instead must scan into a []Idea, then iterate over it to copy all the elements to a []UserCreatedEntity and return that.

How to pass type to function argument in Go

ERROR: type CustomStruct is not an expression.
type CustomStruct struct {
}
func getTypeName(t interface{}) string {
rt := reflect.TypeOf(t).Elem()
return rt.Name()
}
getTypeName(CustomStruct)
How can I pass struct type to function without type instance?
This will work
getTypeName((*CustomStruct)(nil))
But I wonder if there is more simple version..
You can't. You can only pass a value, and CustomStruct is not a value but a type. Using a type identifier is a compile-time error.
Usually when a "type" is to be passed, you pass a reflect.Type value which describes the type. This is what you "create" inside your getTypeName(), but then the getTypeName() will have little left to do:
func getTypeName(t reflect.Type) string {
return t.Name()
}
// Calling it:
getTypeName(reflect.TypeOf(CustomStruct{}))
(Also don't forget that this returns an empty string for anonymous types such as []int.)
Another way is to pass a "typed" nil pointer value as you did, but again, you can just as well use a typed nil value to create the reflect.Type too, without creating a value of the type in question, like this:
t := reflect.TypeOf((*CustomStruct)(nil)).Elem()
fmt.Println(t.Name()) // Prints CustomStruct
Lets resurrect this!
The generics proposal for Go got approved, and that's coming, eventually. When this question was first asked, this probably made more sense as a question, but for anyone looking to implement a generics pattern now, I think I've got an alright API for it.
For now, you can't interact with abstract types, but you can interact with methods on the abstract type, and reflect allows you to examine function signatures. For a method, the 0th is the receiver.
type Example struct {int}
type Generic struct{reflect.Type}
func (p Example) Type() {}
func Reflect(generic interface{}) Generic {
real := reflect.TypeOf(generic)
if real.Kind() != reflect.Func || real.NumIn() < 1 {
panic("reflect.Type.In(n) panics if not a func and if n out of bounds")
}
return Generic{real.In(0)}
}
func (g Generic) Make() interface{} {
return reflect.Zero(g.Type).Interface()
}
func main() {
tOfp := Reflect(Example.Type)
fmt.Printf("Name of the type: %v\n", tOfp.Name())
fmt.Printf("Real (initial)value: %v\n", tOfp.Make())
}
Some quick notes:
The structure of "Example" doesn't matter, rather only that it has a method with a non-pointer receiver.
The definition of a type called "Generic" as a struct is to accomplish what I believed OP's actual intent to be.
The above definition of "Generic" is a struct instead of an interface so that it can have its own method set. Defining "Generic" as an interface, and using a methodset specific to each operand-type used with it would make tons of sense.
If you weren't aware, actual generics are coming in Go 1.18. My example above has no linter or compile protection, and will panic at runtime if used incorrectly. It does work, and will let you reason over abstract types while you wait for a native implementation.
Happy Coding!
From Go version 1.18 a new feature Generics has been introduced. In most of the case instead of passing types to function, we can use generics. Then we will also get compile time error instead of runtime error and it's more efficient than reflect also.
Example Code
func HttpGet[T](url, body) T {
var resp T
return T
}
resp := HttpGet[ResponseType]("dummy.example", nil)

golang: accessing value in slice of interfaces

I have a data structure which comes of out go-spew looking like this:
([]interface {}) (len=1 cap=1) {
(string) (len=1938) "value"
}
It is of type []interface {}
How can I print this value with fmt, or access it in some way so that I can use it.
You can use type assertions or reflection work with the generic interface{} to an underlying type. How you do this depends on your particular use case. If you can expect the interface{} to be a []interface{} as in your example, you can:
if sl, ok := thing.([]interface{}); ok {
for _, val := range sl {
fmt.Println(val)
// Or if needed, coerce val to its underlying type, e.g. strVal := val.(string)
}
}
(Playground link)
If you can't make assumptions about the underlying type, you'll need to do some black magic using reflect.

Using map[string]int as parameter of type map[interface{}]interface{}

I have a function:
func ReturnTuples(map_ map[interface{}]interface{}) [][]interface{} {
In which I'm trying to call like this:
m := make(map[string]int)
m["k1"] = 7
m["k2"] = 13
fmt.Println(ReturnTuples(m))
But I'm getting
cannot use m (type map[string]int) as type map[interface {}]interface {} in argument to ReturnTuples
Shouldn't it work since string and int both implement interface{}?
I've searched and the best I could find was Convert map[interface {}]interface {} to map[string]string but it won't answer why I cannot use m as an argument.
I also believe that if the argument of the function were only interface{} it would work too, since map[something][something] implements interface, right? What is the best way to do it, and why it won't work in my case?
A solution to your problem, simply initiate the map as an empty interface of empty interfaces:
m := map[interface{}]interface{}
then you can assign any type key or value you want in the 'ReturnTuples' function.
playground example
NOTE: remember that if you want to use the values later as the original types, you will need to use type assertion because now they are of type interface{}
You may do something this like this, were anything is one map value which you can get using a for loop:
switch v := anything.(type) {
case string:
fmt.Println(v)
case int32, int64:
fmt.Println(v)
case string:
fmt.Println(v)
case SomeCustomType:
fmt.Println(v)
default:
fmt.Println("unknown")
}
If you are looking for an explanation for the "why"
#ymonad gave a full answer so I wont repeat it again.
hope it make sense
PS: don't get the down votes on the question, a legit one in my eyes...
You can type assert in the function itself.
func test(m interface{},key interface{}) bool { // Map is passed as reference
ma := m.(map[interface{}]interface{})
if _, ok := ma[key]; ok == false {
....
}

Instance new Type (Golang)

Can anyone tell me how to create a new instance of Type from a string? Reflect?
There are examples but they are for the older (pre Go 1 versions) of the language [:(]
So, if I understand your question correctly, you are asking about how you can create an object when you just have the name of the type as string. So, for example, you might have a string "MyStruct" and you want to create an object of this type.
Unfortunately, that's not easily possible because Go is a statically typed language and the linker will eliminate dead code (or inline parts of it). So, there is no guarantee, that your final executable will even contain the code of "MyStruct".
You can however, maintain a global map[string]reflect.Type manually. For example by initializing this map in the init() function of your packages which defines such discover-able types. This will also tell the compiler that you are using the types. Afterwards, you can use this map to look up the reflect.Type of the type you want to create and use reflect.New to get a pointer to a new object of that type (stored as a reflect.Value). You can extract the object into an interface with something like this:
reflect.New(yourtype).Elem().Interface()
Elem() will de-reference the pointer and Interface() will return the reflected value as an interface{}. See The Laws of Reflection for further details.
PS: There might be a better way to structure your program which doesn't even require reflection and which let the compiler catch more errors. Have you considered using a factory method for example? An other easy solution might be to maintain a map[string]func() interface{} of functions which can be invoked to create a new object with that name.
Factory with predefined constructors can be based on something like:
package main
import (
"fmt"
)
type Creator func() interface{}
type A struct {
a int
}
type B struct {
a bool
}
func NewA() interface{} {
return new(A)
}
func NewB() interface{} {
return new(B)
}
func main() {
m := map[string]Creator{}
m["A"] = NewA
m["B"] = NewB
for k, v := range m {
fmt.Printf("%v -> %v\n", k, v())
}
}

Resources