How builtin function "append" works: appending to a slice whose elements are of type interface - go

The section of appending to slices on the specification, mentions the following example:
var t []interface{}
t = append(t, 42, 3.1415, "foo") // t == []interface{}{42, 3.1415, "foo"}
I'm confused here, why can we append values of int, float and string to a slice whose elements are of interface type? And why is the result of the append like that? I tried hard/long, but I don't get it.

Because:
all types implement the empty interface
For details read over the ref spec for interfaces.
interface is similar to Object in java where all types/classes/etc are also an Object.
You can see this effect by using reflect:
package main
import (
"fmt"
"reflect"
)
func main() {
var t []interface{}
z := append(t, "asdf", 1, 2.0)
fmt.Println(z)
for i := range z {
fmt.Println(reflect.TypeOf(z[i]))
}
}
Output:
[asdf 1 2]
string
int
float64
Why is it like this? Well, think about serialization especially of JSON objects; the types can be string, int, object, etc. This allows for deserialization without specifying a fully mapped struct (maybe you don't care and want only some of the data, etc). Basically, it allows you to have a form of "weak typing" in Go; while still being able to have strong typing.
As mentioned below, reflect identifies the type for you. When programming though, you may have to do it manually.

Related

When to store pointers to structs in variables instead of the struct itself

I'm currently learning Go and am following a tutorial about how to use Go with Stripe. There is this example code:
package main
import (
"fmt"
"github.com/stripe/stripe-go"
"github.com/stripe-go/customer"
)
func main() {
sc := &client.API{}
sc.Init("somekey")
c, _ := sc.Customers.Get("customerid", nil)
// ...
}
What is/could be the reason that sc stores the pointer to the struct and not the struct itself?
[To supplement the comment you received]
While in this case with the small code sample it's hard to say, in most scenarios you'll see non-trivial types passed around by pointer to enable modification. As an anti-example, consider this code which uses a variable of a struct type by value:
type S struct {
ID int
}
func (s S) UpdateID(i int) {
s.ID = i
}
func main() {
s := S{}
s.UpdateID(99)
fmt.Println(s.ID)
}
What do you think this will print? It will print 0, because methods with value receivers cannot modify the underlying type.
There's much information about this in Go - read about pointers, and about how methods should be written. This is a good reference: https://golang.org/doc/faq#methods_on_values_or_pointers, and also https://golang.org/doc/effective_go#pointers_vs_values
Back to your example: typically non-trivial types such as those representing a "client" for some services will be using pointers because method calls on such types should be able to modify the types themselves.

casting reflected value to type in golang?

Is it possible to dynamically cast a value generated by reflect.Zero/New back to an arbitrary type?
https://blog.golang.org/laws-of-reflection seems to suggest not (as go is statically typed). That pretty much seems to limit the uses of reflection as far as I can see, as you always need to be aware of the type you are working with.
Here's an example of what I mean:
package main
import (
"fmt"
"reflect"
)
type A struct {
Name string
}
func main() {
a := &A{Name: "Dave"}
fmt.Println(a)
//create a nil pointer of an arbitrary type
dynamicType := reflect.TypeOf(a)
dynamicNil := reflect.Zero(dynamicType).Interface()
a = dynamicNil //is it possible to do this without explicitly casting to A (ie. avoiding `a = dynamicNil.(*A)`)
fmt.Println(a)
}
Your question's prose and code contradict.
In your code, dynamicNil has the type interface{}, not reflect.Value as the prose suggests. As a has concrete type *A you'll have to type-assert dynamicNil to *A. There's no way around that.
Also note that Go doesn't have casts -- only type-conversions and assertions.
Edit: maybe you're looking for reflect.Value.Set? it's unclear to me.

reusing the methods of the base type in the derived custom type in golang

i want to create a ReverseSort method on sort.IntSlice. So i created a custom type of MySlice and added a method of ReverseSort to it.
package main
import (
"fmt"
"sort"
)
type MySlice sort.IntSlice
func (ms MySlice) ReverseSort() {
sort.Sort(sort.Reverse(ms))
}
func main() {
t2 := MySlice{5, 4, 3, 1}
t2.ReverseSort()
fmt.Println(t2)
}
But on running this program error is shown that
cannot use ms (type MySlice) as type sort.Interface in argument to sort.Reverse:
MySlice does not implement sort.Interface (missing Len method)
Is there a way by which i can implement this without creating my own Len , Swap and Less methods for my custom type.
You could embed sort.IntSlice in your custom type:
type MySlice struct {
sort.IntSlice
}
func (ms MySlice) ReverseSort() {
sort.Sort(sort.Reverse(ms))
}
func main() {
t2 := MySlice{sort.IntSlice{5, 4, 3, 1}}
t2.ReverseSort()
fmt.Println(t2)
}
(On the Go Playgroud.)
Of course, that makes constructing objects more difficult.
A post on golang-nuts discusses this:
You "cannot define new methods on non-local type[s]," by design.
The best practice is to embed the non-local type into your own own
local type, and extend it. Type-aliasing (type MyFoo Foo) creates a
type that is (more-or-less) completely distinct from the original. I'm
not aware of a straightforward/best-practice way to use type
assertions to get around that.
Peter Bourgon
And:
A type's methods are in the package that defines it.
This is a logical coherence. It is a compilation virtue. It is seen as
an important benefit for large-scale maintenance and multi-person
development projects.
The power you speak of is not lost, though, because you can embed the
base type in a new type as described above and add whatever you want
to it, in the kind of functional "is a" that you seek, with the only
caveat that your new type must have a new name, and all of its fields
and methods must be in its new package.
Michael Jones

Instantiating a struct via name using a string in go

I am trying to create a function that takes a []byte and an interface{} (standing for the struct) and returns an interface{} as the struct type passed into the func.
Something like this:
package main
import (
"encoding/json"
)
func UnmarshalFromJSONArray(sms []byte,tt string) (interface{}) {
var ts = new(tt)
err := json.Unmarshal(sms,&ts)
if(err != nil) {
fmt.Println(err)
}
return sms
}
So that method would run something like this:
// let's say a struct has the following definition:
type MyStructType struct {
Id int
Name string
Desc string
}
// we can some how get its fully qualified class name (this may require reflection?) or pass it into the UnMarshal method direction some how.
mst := "package.MyStructType",
// and then assume a byte array ba that has JSON format for
ba := []byte(`{"Id":"3","Name":"Jack","Desc":"the man"}`)
stct := UnmarshalFromJSONArray(ba,mst)
MyStructureType out := stct
// leaving "stct" being the unmarshalled byte array which can be used like any other struct of type "MyStructureType"
The key being that I never need to know what the fields of MyStructureType are before unmarshalling. All I need are the name of the struct and some way to instance one and then populate it with JSON byte array data that matches its fields. Hopefully that is possible (it is trivial in java using reflection). So I want to basically unmarshal an anonymous struct type by it's name without needing to know what fields it has.
Any suggestions?
The short answer is that this is impossible. There is no string to type translator in Go. You can make a map of strings to reflect.Type's, but you would need to know the possible options ahead of time or you need to provide the caller with a way to register types (perhaps in init).
Assuming you have found a way to resolve the string to its reflect.Type, you can simply call reflect.New(typ).Interface() to get the pointer you need to pass to json.Unmarshal().
The best answer is to avoid trying this all together. Writing idiomatic Java in Go isn't really possible. If I knew more about your problem, I could give you a more idiomatic Go solution.

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