如何在Golang中重用结构体键?

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

How to reuse struct keys on golang?

问题

有没有办法将一个结构体的键用于另一个结构体?

例如,我有以下结构体:

type Player struct {
	Age       uint8      `json:"age"`
	Name      string     `json:"name"`
	UUID      string     `json:"uuid"`
}

type PlayerDynamo struct {
    // 我希望将Player的所有键与`Salary`处于同一级别。
	// Age       uint8      `json:"age"`
	// Name      string     `json:"name"`
	// UUID      string     `json:"uuid"`
	Salary float32 `json:"salary"`
}

如何声明PlayerDynamo以使用与Player相同的键?

英文:

Is there a way to use the keys from a struct into another struct?

For example I have the following struct:

type Player struct {
	Age       uint8      `json:"age"`
	Name      string     `json:"name"`
	UUID      string     `json:"uuid"`
}

type PlayerDynamo struct {
    // I want all the keys from Player at the same level as `Salary`.
	// Age       uint8      `json:"age"`
	// Name      string     `json:"name"`
	// UUID      string     `json:"uuid"`
	Salary float32 `json:"salary"`
}

How could I declare PlayerDynamo to use the same keys as Player ?

答案1

得分: 7

Go支持一种独特的特性,称为"结构体嵌入"或者只是"嵌入",这是一种一流的组合方式(与大多数面向对象编程语言提供的一流继承相比)。

嵌入允许你在一个结构体中嵌入另一个结构体,这样嵌入结构体的成员可以像在父结构体上声明的一样被引用:

type Player struct {
    Age       uint8      `json:"age"`
    Name      string     `json:"name"`
    UUID      string     `json:"uuid"`
}

type PlayerDynamo struct {
    Player // PlayerDynamo "嵌入" Player
    Salary float32 `json:"salary"`
}

现在,PlayerDynamo的实例既有一个Player成员...

p := PlayerDynamo{}
p.Player.Name

Player的嵌入字段:

p := PlayerDynamo{}
p.Name // 等同于 p.Player.Name

甚至可以在PlayerDynamo上调用Player的方法:

func (p Player) String() string {
  return fmt.Sprintf("Player %q", p.Name)
}

p := PlayerDynamo{
  Player: Player {
    Name: "Bob",
  },
}

fmt.Println(p.String()) // Player "Bob"

这并不完全等同于将Age/Name/UUID字段复制到PlayerDynamo中:当你声明一个新的PlayerDynamo时,仍然需要显式地初始化嵌入的Player

p := PlayerDynamo {
  Player: Player {
    Name: "test",
    Age: 45,
  },
  Salary: 42,
}

关键是,结构体标签会被复制过来,将结构体编组为JSON时,所有的Player字段都会出现在PlayerDynamo的编组表示中。

请参考https://play.golang.org/p/6HMrlVZzIsn 查看一个实时示例。

英文:

Go supports a somewhat unique feature called "struct embedding" or just "embedding", a type of first-class composition (vs what most OOP languages offer, first-class inheritance).

Embedding allows you to embed one struct within another, such that the members of the embedded struct can be referenced as though they were declared on the parent structure:

type Player struct {
    Age       uint8      `json:"age"`
    Name      string     `json:"name"`
    UUID      string     `json:"uuid"`
}

type PlayerDynamo struct {
    Player // PlayerDynamo "embeds" Player
    Salary float32 `json:"salary"`
}

An instance of a PlayerDynamo now has both a Player member...

p := PlayerDynamo{}
p.Player.Name

and the embedded fields of Player:

p := PlayerDynamo{}
p.Name // Equivalent to p.Player.Name

Even methods of Player can be invoked on a PlayerDynamo:

func (p Player) String() string {
  return fmt.Sprintf("Player %q", p.Name)
}

p := PlayerDynamo{
  Player: Player {
    Name: "Bob",
  },
}

fmt.Println(p.String()) // Player "Bob"

This isn't exactly the same as copying the Age/Name/UUID fields into the PlayerDynamo: When you declare a new PlayerDynamo, you still need to initialize the embedded Player explicitly:

p := PlayerDynamo {
  Player: Player {
    Name: "test",
    Age: 45,
  }
  Salary: 42
}

Critically, the struct tags are copied over and marshalling to JSON works as expected, with all of the Player fields appearing within the marshalled representation of a PlayerDynamo.

See https://play.golang.org/p/6HMrlVZzIsn for a live example.

答案2

得分: 0

使用嵌入式结构:

type PlayerDynamo struct {
   Player
   Salary float32 `json:"salary"`
}
英文:

Use embedding:

type PlayerDynamo struct {
   Player
   Salary float32 `json:"salary"`
}

huangapple
  • 本文由 发表于 2021年6月9日 06:28:14
  • 转载请务必保留本文链接:https://go.coder-hub.com/67895315.html
匿名

发表评论

匿名网友

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

确定