I wants to assign a map to an interface where underlying value is of type map[string]interface.
type Data struct{
data interface{}
}
result := make(map[string]interface{})
data := Data{
data:result
}
details := make(map[string]interface{})
details["CreatedFor"] = "dfasfasdf"
details["OwnedBy"] = "fasfsad"
How can I insert details value to data interface inside Data struct ?
To be able to treat an interface as a map, you need to type check it as a map first.
I've modified your sample code a bit to make it clearer, with inline comments explaining what it does:
package main
import "fmt"
func main() {
// Data struct containing an interface field.
type Data struct {
internal interface{}
}
// Assign a map to the field.
type myMap map[string]interface{}
data := Data{
internal: make(myMap),
}
// Now, we want to access the field again, but as a map:
// check that it matches the type we want.
internalMap, ok := data.internal.(myMap)
if !ok {
panic("data.internal is not a map")
}
// Now what we have the correct type, we can treat it as a map.
internalMap["CreatedFor"] = "dfasfasdf"
internalMap["OwnedBy"] = "fasfsad"
// Print the overall struct.
fmt.Println(data)
}
This outputs:
{map[CreatedFor:dfasfasdf OwnedBy:fasfsad]}
Related
I have a function that has a parameter with the type interface{}, something like:
func LoadTemplate(templateData interface{}) {
In my case, templateData is a struct, but each time it has a different structure. I used the type "interface{}" because it allows me to send all kind of data.
I'm using this templateData to send the data to the template:
err := tmpl.ExecuteTemplate(w, baseTemplateName, templateData)
But now I want to append some new data and I don't know how to do it because the "interface" type doesn't allow me to add/append anything.
I tried to convert the interface to a struct, but I don't know how to append data to a struct with an unknown structure.
If I use the following function I can see the interface's data:
templateData = appendAssetsToTemplateData(templateData)
func appendAssetsToTemplateData(t interface{}) interface{} {
switch reflect.TypeOf(t).Kind() {
case reflect.Struct:
fmt.Println("struct")
s := reflect.ValueOf(t)
fmt.Println(s)
//create a new struct based on current interface data
}
return t
}
Any idea how can I append a child to the initial interface parameter (templateData)? Or how can I transform it to a struct or something else in order to append the new child/data?
Adrian is correct. To take it a step further, you can only do anything with interfaces if you know the type that implements that interface. The empty interface, interface{} isn't really an "anything" value like is commonly misunderstood; it is just an interface that is immediately satisfied by all types.
Therefore, you can only get values from it or create a new "interface" with added values by knowing the type satisfying the empty interface before and after the addition.
The closest you can come to doing what you want, given the static typing, is by embedding the before type in the after type, so that everything can still be accessed at the root of the after type. The following illustrates this.
https://play.golang.org/p/JdF7Uevlqp
package main
import (
"fmt"
)
type Before struct {
m map[string]string
}
type After struct {
Before
s []string
}
func contrivedAfter(b interface{}) interface{} {
return After{b.(Before), []string{"new value"}}
}
func main() {
b := Before{map[string]string{"some": "value"}}
a := contrivedAfter(b).(After)
fmt.Println(a.m)
fmt.Println(a.s)
}
Additionally, since the data you are passing to the template does not require you to specify the type, you could use an anonymous struct to accomplish something very similar.
https://play.golang.org/p/3KUfHULR84
package main
import (
"fmt"
)
type Before struct {
m map[string]string
}
func contrivedAfter(b interface{}) interface{} {
return struct{
Before
s []string
}{b.(Before), []string{"new value"}}
}
func main() {
b := Before{map[string]string{"some": "value"}}
a := contrivedAfter(b)
fmt.Println(a)
}
You can't append data arbitrarily to a struct; they're statically typed. You can only assign values to the fields defined for that specific struct type. Your best bet is probably to use a map instead of structs for this.
Not recommended, but you can create structs dynamically using the reflect package.
Here is an example:
package main
import (
"encoding/json"
"os"
"reflect"
)
type S struct {
Name string
}
type D struct {
Pants bool
}
func main() {
a := Combine(&S{"Bob"}, &D{true})
json.NewEncoder(os.Stderr).Encode(a)
}
func Combine(v ...interface{}) interface{} {
f := make([]reflect.StructField, len(v))
for i, u := range v {
f[i].Type = reflect.TypeOf(u)
f[i].Anonymous = true
}
r := reflect.New(reflect.StructOf(f)).Elem()
for i, u := range v {
r.Field(i).Set(reflect.ValueOf(u))
}
return r.Addr().Interface()
}
You could use something like the Combine function above to shmush any number of structs together. Unfortunately, from the documentation:
StructOf currently does not generate wrapper methods for embedded fields. This limitation may be lifted in a future version.
So your created struct won't inherit methods from the embedded types. Still, maybe it does what you need.
If you are just looking to convert your interface to struct, use this method.
type Customer struct {
Name string `json:"name"`
}
func main() {
// create a customer, add it to DTO object and marshal it
receivedData := somefunc() //returns interface
//Attempt to unmarshall our customer
receivedCustomer := getCustomerFromDTO(receivedData)
fmt.Println(receivedCustomer)
}
func getCustomerFromDTO(data interface{}) Customer {
m := data.(map[string]interface{})
customer := Customer{}
if name, ok := m["name"].(string); ok {
customer.Name = name
}
return customer
}
I expected in code to Work with struct Dish was EXPORTED as Dish.
I expected the program to fail when a structure dish was unexported and not see the unexported field within it. (OK, I could see the unexported field being present in an EXPORTED STRUCTURE, but even that seems wrong).
But program still works as shown?? How can the reflection package see 'dish' if it is unexported?
--------------Program Follows----------
//Modified Example From blog: http://merbist.com/2011/06/27/golang-reflection-exampl/
package main
import (
"fmt"
"reflect"
)
func main() {
// iterate through the attributes of a Data Model instance
for name, mtype := range attributes(&dish{}) {
fmt.Printf("Name: %s, Type: %s\n", name, mtype)
}
}
// Data Model
type dish struct {
Id int
last string
Name string
Origin string
Query func()
}
// Example of how to use Go's reflection
// Print the attributes of a Data Model
func attributes(m interface{}) map[string]reflect.Type {
typ := reflect.TypeOf(m)
// if a pointer to a struct is passed, get the type of the dereferenced object
if typ.Kind() == reflect.Ptr {
typ = typ.Elem()
}
// create an attribute data structure as a map of types keyed by a string.
attrs := make(map[string]reflect.Type)
// Only structs are supported so return an empty result if the passed object
// isn't a struct
if typ.Kind() != reflect.Struct {
fmt.Printf("%v type can't have attributes inspected\n", typ.Kind())
return attrs
}
// loop through the struct's fields and set the map
for i := 0; i < typ.NumField(); i++ {
p := typ.Field(i)
fmt.Println("P = ", p)
if !p.Anonymous {
attrs[p.Name] = p.Type
}
}
return attrs
}
From: https://blog.golang.org/laws-of-reflection
the field names of T are upper case (exported) because only exported fields of a struct are settable."
This easily shows and proves the concept:
fmt.Printf("can set 'last'? %v; can set 'Id'? %v",
reflect.ValueOf(&dish{}).Elem().FieldByName("last").CanSet(),
reflect.ValueOf(&dish{}).Elem().FieldByName("Id").CanSet(),
)
This prints: can set 'last'? false; can set 'Id'? true
On the visibility of the type (struct) name ("dish" vs "Dish") that only affects the visibility when you directly use the type at compile time. For example:
import "whatever/something"
...
v := something.someStruct{} // will give compile error
...
// this can return an instance of someStruct, which can be inspected
// with reflect just like any other struct (and that works fine because
// we haven't directly put a literal "something.someStruct" in this code
v := something.SomeFunc()
I have some JSON and I need to be able to access the properties. As the JSON properties can vary I can't create a struct to unmarshal into.
Example
The JSON could be this:
{"name" : "John Doe", "email" : "john#doe.com"}
or this:
{"town" : "Somewhere", "email" : "john#doe.com"}
or anything else.
How can I access each of the properties?
You can unmarshal it into an interface{}. If you do that, json.Unmarshal will unmarshal a JSON object into a Go map.
For example:
var untypedResult interface{}
err := json.Unmarshal(..., &untypedResult)
result := untypedResult.(map[string]interface{})
// ... now you can iterate over the keys and values of result ...
See <http://blog.golang.org/json-and-go#TOC_5.> for a complete example.
If you just happen to have fields that may not be specified, you can unmarshal your input into a struct with pointer. If the field isn't present, the pointer will be nil.
package main
import (
"encoding/json"
"fmt"
)
type Foo struct {
A *string
B *string
C *int
}
func main() {
var input string = `{"A": "a","C": 3}`
var foo Foo
json.Unmarshal([]byte(input), &foo)
fmt.Printf("%#v\n", foo)
}
Playground
If you really want something more flexible, you can also unmarshal your input into a map[string]interface{}.
package main
import (
"encoding/json"
"fmt"
)
func main() {
var input string = `{"A": "a","C": 3}`
var foo map[string]interface{} = make(map[string]interface{})
json.Unmarshal([]byte(input), &foo)
fmt.Printf("%#v\n", foo)
}
Playground
When unmarshalling a JSON document, not all properties that are defined in the struct need to be present in the JSON document. In your example, you could define the following struct:
type MyJson struct {
Name string `json:"name"`
Town string `json:"town"`
Email string `json:"email"`
}
When your use this struct to unmarshal a JSON document that has one or more of these properties missing, they will be initialized with the respective type's null value (an empty string for string properties).
Alternatively, you can use the generic interface{} type for unmarshalling and then use type assertions. This is documented in-depth in the blog post "JSON and GO":
var jsonDocument interface{}
err := json.Unmarshal(jsonString, &jsonDocument)
map := jsonDocument.(map[string]interface{})
town := map["town"].(string);
I saw somewhere, but I do not remember where, that a slice struct is passing through function like the following code snippet.
package main
import "fmt"
func passSlice(arg interface{}) {
fmt.Println(arg)
}
func main() {
res := []struct {
Name string
}{}
passSlice(res)
}
I have no idea, how to use here a slice struct in the function. Have someone a idea, how can I use it in the function?
In order to use the slice struct (or any other value stored in an interface), you must first do a type assertion or type switch:
Type assertion:
func passSlice(arg interface{}) {
// Put args value in v if it is of type []struct{ Name string }
v, ok := arg.([]struct{ Name string })
if !ok {
// did not contain a value of type []struct{Name string}
return
}
for _, s := range v {
fmt.Println(s.Name)
}
}
Playground: http://play.golang.org/p/KiFeVC3VQ_
Type switches are similar, but can have cases for multiple types.
There is also an option of using the reflect package, allowing you to more dynamically handle interface values without knowing before hand what types you can expect, but using reflection is also more complex. To know more about using reflection in Golang, you can look here:
Laws of reflection
reflect package
In Go, how do you create the instance of an object from its type at run time? I suppose you would also need to get the actual type of the object first too?
I am trying to do lazy instantiation to save memory.
In order to do that you need reflect.
package main
import (
"fmt"
"reflect"
)
func main() {
// one way is to have a value of the type you want already
a := 1
// reflect.New works kind of like the built-in function new
// We'll get a reflected pointer to a new int value
intPtr := reflect.New(reflect.TypeOf(a))
// Just to prove it
b := intPtr.Elem().Interface().(int)
// Prints 0
fmt.Println(b)
// We can also use reflect.New without having a value of the type
var nilInt *int
intType := reflect.TypeOf(nilInt).Elem()
intPtr2 := reflect.New(intType)
// Same as above
c := intPtr2.Elem().Interface().(int)
// Prints 0 again
fmt.Println(c)
}
You can do the same thing with a struct type instead of an int. Or anything else, really. Just be sure to know the distinction between new and make when it comes to map and slice types.
As reflect.New doesn't automatically make reference types used in struct fields, you could use something like the following to recursively initialize those field types (note the recursive struct definition in this example):
package main
import (
"fmt"
"reflect"
)
type Config struct {
Name string
Meta struct {
Desc string
Properties map[string]string
Users []string
}
}
func initializeStruct(t reflect.Type, v reflect.Value) {
for i := 0; i < v.NumField(); i++ {
f := v.Field(i)
ft := t.Field(i)
switch ft.Type.Kind() {
case reflect.Map:
f.Set(reflect.MakeMap(ft.Type))
case reflect.Slice:
f.Set(reflect.MakeSlice(ft.Type, 0, 0))
case reflect.Chan:
f.Set(reflect.MakeChan(ft.Type, 0))
case reflect.Struct:
initializeStruct(ft.Type, f)
case reflect.Ptr:
fv := reflect.New(ft.Type.Elem())
initializeStruct(ft.Type.Elem(), fv.Elem())
f.Set(fv)
default:
}
}
}
func main() {
t := reflect.TypeOf(Config{})
v := reflect.New(t)
initializeStruct(t, v.Elem())
c := v.Interface().(*Config)
c.Meta.Properties["color"] = "red" // map was already made!
c.Meta.Users = append(c.Meta.Users, "srid") // so was the slice.
fmt.Println(v.Interface())
}
You can use reflect.Zero() which will return the representation of the zero value of the struct type. (similar to if you did var foo StructType) This is different from reflect.New() as the latter will dynamically allocate the struct and give you a pointer, similar to new(StructType)
Here's a basic example like Evan Shaw gave, but with a struct:
package main
import (
"fmt"
"reflect"
)
func main() {
type Product struct {
Name string
Price string
}
var product Product
productType := reflect.TypeOf(product) // this type of this variable is reflect.Type
productPointer := reflect.New(productType) // this type of this variable is reflect.Value.
productValue := productPointer.Elem() // this type of this variable is reflect.Value.
productInterface := productValue.Interface() // this type of this variable is interface{}
product2 := productInterface.(Product) // this type of this variable is product
product2.Name = "Toothbrush"
product2.Price = "2.50"
fmt.Println(product2.Name)
fmt.Println(product2.Price)
}
Per newacct's response, using Reflect.zero it would be:
var product Product
productType := reflect.TypeOf(product) // this type of this variable is reflect.Type
productValue := reflect.Zero(productType) // this type of this variable is reflect.Value
productInterface := productValue.Interface() // this type of this variable is interface{}
product2 := productInterface.(Product) // the type of this variable is Product
This is a great article on the basics of reflection in go.
You don't need reflect and you can do this easy with factory pattern if they share the same interface:
package main
import (
"fmt"
)
// Interface common for all classes
type MainInterface interface {
GetId() string
}
// First type of object
type FirstType struct {
Id string
}
func (ft *FirstType) GetId() string {
return ft.Id
}
// FirstType factory
func InitializeFirstType(id string) MainInterface {
return &FirstType{Id: id}
}
// Second type of object
type SecondType struct {
Id string
}
func (st *SecondType) GetId() string {
return st.Id
}
// SecondType factory
func InitializeSecondType(id string) MainInterface {
return &SecondType{Id: id}
}
func main() {
// Map of strings to factories
classes := map[string]func(string) MainInterface{
"first": InitializeFirstType,
"second": InitializeSecondType,
}
// Create a new FirstType object with value of 10 using the factory
newObject := classes["first"]("10")
// Show that we have the object correctly created
fmt.Printf("%v\n", newObject.GetId())
// Create a new SecondType object with value of 20 using the factory
newObject2 := classes["second"]("20")
// Show that we have the object correctly created
fmt.Printf("%v\n", newObject2.GetId())
}