可以使用Go语言向现有的结构体添加字段吗?

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

Can I add a field to an existing struct with Go?

问题

假设我有以下结构体:

type Planet struct {
    Name       string  `json:"name"`
    Aphelion   float64 `json:"aphelion"`   // in million km
    Perihelion float64 `json:"perihelion"` // in million km
    Axis       int64   `json:"axis"`       // in km
    Radius     float64 `json:"radius"`
}

以及该结构体的实例,例如:

var mars = &Planet{
    Name:       "Mars",
    Aphelion:   249.2,
    Perihelion: 206.7,
    Axis:       227939100,
    Radius:     3389.5,
}

var earth = &Planet{
    Name:       "Earth",
    Aphelion:   151.930,
    Perihelion: 147.095,
    Axis:       149598261,
    Radius:     6371.0,
}

var venus = &Planet{
    Name:       "Venus",
    Aphelion:   108.939,
    Perihelion: 107.477,
    Axis:       108208000,
    Radius:     6051.8,
}

现在我想为所有这些实例添加一个字段,例如Mass。我该如何做呢?

目前,我会定义一个新的结构体,例如PlanetWithMass,并逐个字段重新赋值给PlanetWithMass的新实例。

是否有一种更简洁的方法来实现呢?一种不需要在Planet更改时进行调整的方法?

编辑:我需要在 Web 服务器上使用这个结构体,并将其作为 JSON 发送,但需要添加一个额外的字段。嵌入无法解决这个问题,因为它会改变生成的 JSON。

英文:

Suppose I have the struct

type Planet struct {
    Name       string  `json:"name"`
    Aphelion   float64 `json:"aphelion"`   // in million km
    Perihelion float64 `json:"perihelion"` // in million km
    Axis       int64   `json:"Axis"`       // in km
    Radius     float64 `json:"radius"`
}

as well as instances of this struct, e.g.

var mars = new(Planet)
mars.Name = "Mars"
mars.Aphelion = 249.2
mars.Perihelion = 206.7
mars.Axis = 227939100
mars.Radius = 3389.5

var earth = new(Planet)
earth.Name = "Earth"
earth.Aphelion = 151.930
earth.Perihelion = 147.095
earth.Axis = 149598261
earth.Radius = 6371.0

var venus = new(Planet)
venus.Name = "Venus"
venus.Aphelion = 108.939
venus.Perihelion = 107.477
venus.Axis = 108208000
venus.Radius = 6051.8

Now I want to add a field, e.g. Mass to all of those. How can I do that?

At the moment, I define a new struct, e.g. PlanetWithMass and reassign all fields - field by field - to new instances of the PlanetWithMass.

Is there a less verbose way to do it? A way which does not need adjustment when Planet changes?

edit: I need this on a web server, where I have to send the struct as JSON, but with an additional field. Embedding does not solve this problem as it changes the resulting JSON.

答案1

得分: 29

你可以将Planet嵌入到PlanetWithMass中:

type PlanetWithMass struct {
    Planet
    Mass float64
}

然后可以这样使用:

marsWithMass := PlanetWithMass{
    Planet: mars,
    Mass: 639e21,
}

有关嵌入的更多信息,请参阅规范Effective Go

Playground

英文:

You could embed Planet into PlanetWithMass:

type PlanetWithMass struct {
    Planet
    Mass float64
}

and do something like

marsWithMass := PlanetWithMass{
    Planet: mars,
    Mass: 639e21,
}

For more info on embedding, see the Spec and Effective Go.

Playground

答案2

得分: 1

你可以使用map[string]string,这样可以明确地添加尽可能多的子键。注意:你需要先声明一个具有一种类型的结构体。

type PlanetWithMass struct {
    Planet map[string]string
}

然后,通过结构体的实例来添加更多的字段。

type PlanetWithMass struct {
    Planet map[string]string
}

planet := &PlanetWithMass{} // 结构体的实例

planet.Planet = make(map[string]string) // 将字段声明为map[string]string类型

planet.Planet["Name"] = "Mercury"
planet.Planet["Galaxy"] = "Milky Way"
planet.Planet["Population"] = "70亿"
planet.Planet["HasOceans"] = "是"

使用这种方法你可以在结构体中添加多个字段而不必担心使用接口这可能是一个取巧的方法但它是有效的

<details>
<summary>英文:</summary>

You can probably use **map[string]string** which will enable you to explicitly add as many sub keys as possible. NOTE: You will have to declare the struct first with one type

`type PlanetWithMass struct {
	Planet map[string]string
}`

Then to add more fields, start by an instance of the struct


    
   
    type PlanetWithMass struct {
      Planet map[string]string
    }

    planet := &amp;PlanetWithMass{} // instance of struct

	planet.Planet = make(map[string]string) // declare field as a map[string]string

	planet.Planet[&quot;Name&quot;] = &quot;Mercury&quot;
	planet.Planet[&quot;Galaxy&quot;] = &quot;Milky Way&quot;
    planet.Planet[&quot;Population&quot;] = &quot;7 Billion&quot;
	planet.Planet[&quot;HasOceans&quot;] = &quot;Yes&quot;

Using this method, you can add several fields to the struct without the worry of using interfaces. It might be a round hack but it works!



</details>



huangapple
  • 本文由 发表于 2015年3月13日 04:45:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/29019864.html
匿名

发表评论

匿名网友

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

确定