Golang可以以不同的方式创建结构体。

huangapple go评论70阅读模式
英文:

Golang create struct in different way

问题

大家好!我是Go语言的初学者。在学习reflect包时,我有一些疑问。以下是代码:

package main

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

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

type Test struct {
	X int
	Y string
}

func main() {
	fmt.Println("hello world!")
	test1()
	test2()
}

func test1() {
	a := Test{}
	fmt.Printf("a: %v %T \n", a, a)
	fmt.Println(a)
	err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
	checkError(err)
	fmt.Printf("a: %v %T \n", a, a)
}

func test2() {
	fmt.Println("===========================")
	m := make(map[string]reflect.Type)
	m["test"] = reflect.TypeOf(Test{})
	a := reflect.New(m["test"]).Elem().Interface()
	fmt.Printf("a: %v %T \n", a, a)
	fmt.Println(a)
	err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
	checkError(err)
	fmt.Printf("a: %v %T \n", a, a)
}

结果如下:

a: {0 } main.Test 
{0 }
a: {1 x} main.Test 
===========================
a: {0 } main.Test 
{0 }
a: map[X:1 Y:x] map[string]interface {}

为什么这两种方式会产生不同的结果?有人能告诉我原因吗?非常感谢。

英文:

guys! I am a beginner in Go. I have some doubts When I learning reflect package ,here's the code:

package main

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

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

type Test struct {
	X int
	Y string
}

func main() {
	fmt.Println("hello world!")
	test1()
	test2()
}

func test1() {
	a := Test{}
	fmt.Printf("a: %v %T \n", a, a)
	fmt.Println(a)
	err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
	checkError(err)
	fmt.Printf("a: %v %T \n", a, a)
}

func test2() {
	fmt.Println("===========================")
	m := make(map[string]reflect.Type)
	m["test"] = reflect.TypeOf(Test{})
	a := reflect.New(m["test"]).Elem().Interface()
	fmt.Printf("a: %v %T \n", a, a)
	fmt.Println(a)
	err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), &a)
	checkError(err)
	fmt.Printf("a: %v %T \n", a, a)
}

and the result :

a: {0 } main.Test 
{0 }
a: {1 x} main.Test 
===========================
a: {0 } main.Test 
{0 }
a: map[X:1 Y:x] map[string]interface {}

Why these two way make different result, Could anyone tell me why, many thanks.

答案1

得分: 2

test2中,您传递了包含Test值的interface{}的地址。当json包解引用该值时,它只看到一个interface{},因此将其解组为默认类型。

您需要的是一个包含指向Test值的指针的interface{}

// reflect.New正在创建一个*Test{}值。
// 您不想使用Elem()解引用它。
a := reflect.New(m["test"]).Interface()

// 'a'包含一个*Test值。您已经有一个指针,而且您不想要接口值的地址。
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), a)
英文:

In test2 you're passing in the address of the interface{} containing a Test value. When the value is dereferenced by the json package it only sees an interface{}, and therefor it unmarshals into the default types.

What you need is an interface{} containing a pointer to a Test value.

// reflect.New is creating a *Test{} value.
// You don't want to dereference that with Elem()
a := reflect.New(m["test"]).Interface()

// 'a' contains a *Test value. You already have a pointer, and you
// don't want the address of the interface value.
err := json.Unmarshal([]byte(`{"X":1,"Y":"x"}`), a)

huangapple
  • 本文由 发表于 2016年1月19日 23:20:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/34880504.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定