Skip to content

Instantly share code, notes, and snippets.

@dulao5
Created August 16, 2018 01:48
Show Gist options
  • Save dulao5/0329590405418ec2f3405ab367ddfdce to your computer and use it in GitHub Desktop.
Save dulao5/0329590405418ec2f3405ab367ddfdce to your computer and use it in GitHub Desktop.
package main
import (
"fmt"
"reflect"
)
func main() {
vars := []interface{}{"1", "2", "3", "4", "5"}
fmt.Println(vars)
targetType := reflect.TypeOf([]string{})
rSlice := reflect.MakeSlice(targetType, len(vars), len(vars))
for index, item := range vars {
targetItem := rSlice.Index(index)
fmt.Println(targetItem.Interface())
srcItem := reflect.ValueOf(item)
targetItem.Set(srcItem)
}
fmt.Println("copy to:")
fmt.Println(rSlice) // [1 2 3 4 5]
}
# from : https://stackoverflow.com/questions/7850140/how-do-you-create-a-new-instance-of-a-struct-from-its-type-at-run-time-in-go
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())
}
@dulao5
Copy link
Author

dulao5 commented Aug 16, 2018

ゴール

package main

import (
	"fmt"
	"reflect"
	"encoding/json"
)

type Config struct {
	Name string		`json:Name`
	Data struct {		`json:Data`
		Desc       string		`json:Desc`
		Properties map[string]string	`json:Properties`
		Users      []string		`json:Users`
	}
}

/*
func coptJsonToStruct(src interface{}, t reflect.Type, v reflect.Value) {
	TODO
}*/

func main() {

	jsonStr := `
	{
		"Name" : "my-name",
		"Data" : {
			"Desc": "desc desc",
			"Properties": {
				"abc": "123",
				"def": "456"
			},
			"Users": [
				"123",
				"456"
			]
		}
	}
	`

	var jsonData interface{}
	json.Unmarshal([]byte(jsonStr), &jsonData)
	
	fmt.Println(jsonData)

	t := reflect.TypeOf(Config{})
	v := reflect.New(t)
	//coptJsonToStruct(jsonData, t, v)

	fmt.Println(v.Interface())
}

@dulao5
Copy link
Author

dulao5 commented Aug 20, 2018

@dulao5
Copy link
Author

dulao5 commented Aug 20, 2018

@dulao5
Copy link
Author

dulao5 commented Aug 29, 2018

https://go-zh.org/ref/spec
Types :
TypeLit = ArrayType | StructType | PointerType | FunctionType | InterfaceType |
SliceType | MapType | ChannelType .

@dulao5
Copy link
Author

dulao5 commented Nov 24, 2018

package main

import (
	"encoding/json"
	"fmt"
	"reflect"
)

type Obj struct {
	Key1 string `json:"k1"`
	Key2 string `json:"k2"`
	Key3 int64  `json:"k3"`
	Key4 int    `json:"k4"`
	Key5 bool   `json:"k5"`
}

func coptJsonMapToStruct(src interface{}, t reflect.Type) reflect.Value {

	srcMap := src.( map[string]interface{})
	p := reflect.New(t) // New returns a Value representing a pointer to a new zero value for the specified type
	fmt.Printf("reflect.New(t) point of : %T\n", p)
	
	// Elem returns the value that the interface v contains or that the pointer v points to. It panics if v's Kind is not Interface or Ptr. It returns the zero Value if v is nil.
	v := p.Elem()
	fmt.Printf("reflect.New(t).Elem() : %T\n", v)
	
	typeOfT := v.Type()
	for i := 0; i < v.NumField(); i++ {
		for j, f := range srcMap {
			if typeOfT.Field(i).Tag.Get("json") == j {
				fl := v.FieldByName(typeOfT.Field(i).Name)
				switch fl.Kind() {
				case reflect.Bool:
					fl.SetBool(f.(bool))
				case reflect.Int, reflect.Int64:
					c, _ := f.(float64)
					fl.SetInt(int64(c))
				case reflect.String:
					fl.SetString(f.(string))
				}
			}
		}
	}
	return p
}

func main() {
	data := `{"k1": "v1", "k2": "v2", "k3": 1234567890, "k4": 456, "k5": true}`
	src := map[string]interface{}{}
	json.Unmarshal([]byte(data), &src)
	
	t := reflect.TypeOf(Obj{})
	fmt.Printf("reflect.TypeOf(Obj{}) : %T\n", t)
	
	p := coptJsonMapToStruct(src, t)
	v := p.Elem()
	fmt.Printf("%+v\n", v) // &{Key1:v1 Key2:v2 Key3:1234567890 Key4:456 Key5:true}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment