如何修改现有结构体中的对象和结构体?

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

How to modify object and struct from an existing struct?

问题

我有一个结构体,如下所示:

type person struct{
    name string
    phone string
    address string
}

我想将其转换为以下形式(修改phone和address)我只有对象,没有结构体。

type person2 struct {
    name  string
    phone []struct {
        value string
    }

    address []struct {
        value string
    }
}

我应该如何基于已有的结构体创建新的结构体?我只想转换选定的字段。

我查看了反射(reflection),但不知道从何开始/如何使用它。

英文:

I have a struct say

type person struct{
	name string
	phone string
	address string
}

and I want to transform it to this (modify phone and address) I only have the object not the struct.

type person2 struct {
	name  string
	phone []struct {
		value string
	}

	address []struct {
		value string
	}
}

How can I create new struct based on one I have ? I want to transform selected fields only.

I looked into reflection but don't know where to start/how to use it.

答案1

得分: 4

**前言:**如果你只有person类型而没有person2类型,你需要先编写person2。Go是一种静态类型语言,你不能在运行时创建person2。你可以手动编写person2,或者使用go generate通过编写生成器代码来生成,但这并不会更简单。

你也可以使用类似map[string]interface{}的方式来模拟动态结构,但这既不友好也不快速。更不用说你还必须使用类型断言,因为值类型是interface{}...


要从person的值创建一个person2的值,你不需要使用反射,可以简单地手动编码:

func transform(p person) person2 {
	return person2{
		p.name,
		[]struct{ value string }{{p.phone}},
		[]struct{ value string }{{p.address}},
	}
}

请注意,这看起来有点奇怪,因为你在person2.phoneperson2.address中使用了匿名结构的切片,并且为了使用复合字面量初始化匿名结构,必须重复匿名结构的定义。

测试一下:

p := person{"Bob", "1234", "New York"}
fmt.Println(p)
p2 := transform(p)
fmt.Println(p2)

输出结果(在Go Playground上尝试):

{Bob 1234 New York}
{Bob [{1234}] [{New York}]}

注意:

注意,你的person2过于复杂了。它可以简化为这样:

type person2 struct {
	name      string
	phones    []string
	addresses []string
}

然后,转换可以变成一行代码:

func transform(p person) person2 {
	return person2{p.name, []string{p.phone}, []string{p.address}}
}

输出结果(在Go Playground上尝试):

{Bob 1234 New York}
{Bob [1234] [New York]}
英文:

Foreword: if you only have the type person and not person2, you have to first write person2. Go is statically typed language, you can't just create person2 at runtime. You may write person2 manually or use go generate by writing the generator code yourself, but it won't be any simpler.

You could also use something like map[string]interface{} to mimic a dynamic struct, but that won't be any friendlier nor faster. Not to mention you'd have to use type assertions as value type is interface{}...


To create a value of person2 from a value of person, you don't need reflection, you can simply manually code it:

func transform(p person) person2 {
	return person2{
		p.name,
		[]struct{ value string }{{p.phone}},
		[]struct{ value string }{{p.address}},
	}
}

Note that this may look a little weird, and that's because you used a slice of anonymous struct for person2.phone and person2.address, and to initialize an anonymous struct with a composite literal, the anonymous struct definition has to be repeated.

Testing it:

p := person{"Bob", "1234", "New York"}
fmt.Println(p)
p2 := transform(p)
fmt.Println(p2)

Output (try it on the Go Playground):

{Bob 1234 New York}
{Bob [{1234}] [{New York}]}

Note:

Note that your person2 is unnecessarily complex. It could be as simple as this:

type person2 struct {
	name      string
	phones    []string
	addresses []string
}

And then the transformation is a one-liner:

func transform(p person) person2 {
	return person2{p.name, []string{p.phone}, []string{p.address}}
}

Output (try it on the Go Playground):

{Bob 1234 New York}
{Bob [1234] [New York]}

huangapple
  • 本文由 发表于 2016年3月21日 14:00:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/36124108.html
匿名

发表评论

匿名网友

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

确定