๊ธ€ ์ž‘์„ฑ์ž: ๋˜ฅํด๋ฒ .
๋ฐ˜์‘ํ˜•

๊ตฌ์กฐ์ฒด ๋ฐ ์ธํ„ฐํŽ˜์ด์Šค ์ •์˜

type Animal interface{
	Move(int) bool
}

type Cat struct {
	Name string `custom:"name"`
	Age int `custom:"age"`
	Child []string `custom:"child"`
}

func (c *Cat) Move(distance int) bool {
	fmt.Println("Cat Move ", distance)
	return true
}

type Dog struct{
	Name string `custom:"name"`
	Age int `custom:"age"`
	Child []string `custom:"child"`
}

func (d *Dog) Move(distance int) bool {
	fmt.Println("Dog Move ", distance)
	return false
}

 

๊ตฌ์กฐ์ฒด ํ•„๋“œ ์ˆœํšŒ (Iterate Struct Field)

func TestCatFieldLoop(t *testing.T) {
	cat := &Cat{
		Name: "nabi",
		Age: 5,
		Child:    []string{"nyang", "kong"},
	}
	LoopObjectField(cat)
}

func LoopObjectField(object interface{}) {
	e := reflect.ValueOf(object).Elem()
	fieldNum := e.NumField()
	for i := 0; i < fieldNum; i ++{
		v := e.Field(i)
		t := e.Type().Field(i)
		fmt.Printf("Name: %s / Type: %s / Value: %v / Tag: %s \n",
			t.Name, t.Type, v.Interface(), t.Tag.Get("custom"))
	}
}
=== RUN   TestCatFieldLoop
Name: Name / Type: string / Value: nabi / Tag: name 
Name: Age / Type: int / Value: 5 / Tag: age 
Name: Child / Type: []string / Value: [nyang kong] / Tag: child 
--- PASS: TestCatFieldLoop (0.00s)
PASS

 

ํƒ€์ž…์„ ํ†ตํ•ด ๊ตฌ์กฐ์ฒด ์ƒ์„ฑ(Create Struct From a Type)

func TestCatCreate(t *testing.T) {
	cat := Cat{
		Name: "nabi",
		Age: 5,
		Child:    []string{"nyang", "kong"},
	}
	cat2 := CreateObject(cat).(Cat)
	cat2 = Cat {
		Name:  "nyang",
		Age:   1,
	}
	fmt.Println("Cat1: ", cat)
	fmt.Println("Cat2: ", cat2)
}

func CreateObject(object interface{}) interface{}{
	e := reflect.TypeOf(object)
	return reflect.New(e).Elem().Interface()
}
=== RUN   TestCatCreate
Cat1:  {nabi 5 [nyang kong]}
Cat2:  {nyang 1 []}
--- PASS: TestCatCreate (0.00s)
PASS

 

ํƒ€์ž…์„ ํ†ตํ•ด ๊ตฌ์กฐ์ฒด ์ƒ์„ฑ(Create Struct From a Type) - ํฌ์ธํ„ฐ(Pointer)

func TestCatCreatePointer(t *testing.T) {
	cat := &Cat{
		Name: "nabi",
		Age: 5,
		Child:    []string{"nyang", "kong"},
	}
	cat2 := CreateObjectPointer(cat).(*Cat)
	cat2.Name = "nyang"
	cat2.Age = 1
	fmt.Println("Cat1: ", cat)
	fmt.Println("Cat2: ", cat2)
}

func CreateObjectPointer(object interface{}) interface{}{
	e := reflect.ValueOf(object).Elem()
	return reflect.New(e.Type()).Interface()
}
=== RUN   TestCatCreatePointer
Cat1:  &{nabi 5 [nyang kong]}
Cat2:  &{nyang 1 []}
--- PASS: TestCatCreatePointer (0.00s)
PASS

 

์Šฌ๋ผ์ด์Šค ํƒ€์ž… ์ˆœํšŒ(Slice Type Loop)

func TestLoopFieldSliceElement(t *testing.T) {
	animals := []Animal{
		&Cat{"nyang", 5, []string{"kong"}},
		&Dog{"mung", 10, nil},
	}
	LoopFieldSliceElement(animals)
}

func LoopFieldSliceElement(object interface{}) {
	v := reflect.ValueOf(object)
	length := v.Len()
	for i := 0; i < length; i++ {
		LoopObjectField(v.Index(i).Interface())
	}
}

func LoopObjectField(object interface{}) {
	e := reflect.ValueOf(object).Elem()
	fieldNum := e.NumField()
	for i := 0; i < fieldNum; i ++{
		v := e.Field(i)
		t := e.Type().Field(i)
		fmt.Printf("Name: %s / Type: %s / Value: %v / Tag: %s \n",
			t.Name, t.Type, v.Interface(), t.Tag.Get("custom"))
	}
}
=== RUN   TestLoopFieldSliceElement
Name: Name / Type: string / Value: nyang / Tag: name 
Name: Age / Type: int / Value: 5 / Tag: age 
Name: Child / Type: []string / Value: [kong] / Tag: child 
Name: Name / Type: string / Value: mung / Tag: name 
Name: Age / Type: int / Value: 10 / Tag: age 
Name: Child / Type: []string / Value: [] / Tag: child 
--- PASS: TestLoopFieldSliceElement (0.00s)
PASS

 

์Šฌ๋ผ์ด์Šค๋ฅผ ํ†ตํ•ด ๊ตฌ์กฐ์ฒด ์ƒ์„ฑ(Create Object From Slice Type)

func TestSliceTypeToObject(t *testing.T) {
	cats := []Cat{
		{"nyang", 5, []string{"kong"}},
		{"kong", 1, nil},
	}
	cat := CreateObjectFromSlice(cats)
	fmt.Printf("%+v\n", cat)
}

func CreateObjectFromSlice(object interface{}) interface{} {
	return reflect.New(reflect.ValueOf(object).Index(0).Type()).Interface()
}
=== RUN   TestSliceTypeToObject
&{Name: Age:0 Child:[]}
--- PASS: TestSliceTypeToObject (0.00s)
PASS

 

์Šฌ๋ผ์ด์Šค๋ฅผ ์ˆœํšŒํ•˜๋ฉด์„œ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ

func TestAnimalMethodCall(t *testing.T) {
	animals := []Animal{
		&Cat{"nyang", 5, []string{"kong"}},
		&Dog{"kong", 1, nil},
	}
	MethodCall(animals)
}

func MethodCall(object interface{}) {
	v := reflect.ValueOf(object)
	length := v.Len()
	for i := 0; i < length; i++ {
		// Method Call
		result := v.Index(i).Elem().MethodByName("Move").Call(
			[]reflect.Value{
				reflect.ValueOf(5),
			},
			)
		// Print Result
		fmt.Println(result[0].Interface())
	}
}
=== RUN   TestAnimalMethodCall
Cat Move  5
true
Dog Move  5
false
--- PASS: TestAnimalMethodCall (0.00s)
PASS

 

ํƒ€์ž…์„ ์ „๋‹ฌํ•˜์—ฌ ์Šฌ๋ผ์ด์Šค๋ฅผ ๋งŒ๋“ค๊ณ  json ๋ฐ์ดํ„ฐ๋ฅผ ์ž…๋ ฅํ•ด ๋งŒ๋“  ์Šฌ๋ผ์ด์Šค์— append

type Cat struct {
	Name string `json:"name"`
	Age int `json:"age"`
	Child []string `json:"child"`
}

func TestCatDataApply(t *testing.T) {
	var cat *Cat
	result := DataApply(cat)
	cats := *(result.(*[]*Cat))
	for _, cat := range cats {
		fmt.Println(cat)
	}
}

func DataApply(object interface{}) interface{} {
	jsonMessage := "{\"name\": \"nyang\", \"age\": 5}"

	objType := reflect.TypeOf(object) // Type: *Cat
	objSlice:= reflect.New(reflect.SliceOf(objType)).Interface() // *[]*Cat (Create Slice []*Cat)

	for i := 0; i < 5; i ++ {
		obj := reflect.New(objType.Elem()).Interface() // *Cat (Create Instance Cat)
		_ = json.Unmarshal([]byte(jsonMessage), obj) // json data apply

		v := reflect.ValueOf(objSlice)
		v.Elem().Set(reflect.Append(v.Elem(), reflect.ValueOf(obj)))
	}
	return objSlice
}
=== RUN   TestCatDataApply
&{nyang 5 []}
&{nyang 5 []}
&{nyang 5 []}
&{nyang 5 []}
&{nyang 5 []}
--- PASS: TestCatDataApply (0.00s)
PASS
๋ฐ˜์‘ํ˜•