在结构体标签中使用变量

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

Using a variable in the struct tag

问题

如何在Go的结构标签中使用变量?

这样可以实现:

type Shape struct {
    Type string `json:"type"`
}

但是这样是不行的:

const (
    TYPE = "type"
)

type Shape struct {
    Type string fmt.Sprintf("json:\"%s\"", TYPE)
}

在第一个示例中,我使用了一个字符串字面量,这是有效的。但在第二个示例中,我使用了fmt.Sprintf构建了一个字符串,似乎出现了错误:
syntax error: unexpected name, expecting }

你可以在Go Playground上查看这个问题的示例:
https://play.golang.org/p/lUmylztaFg

英文:

How would I use a variable in a Go struct tag?

This works:

type Shape struct {
	Type string `json:"type"`
}

This does not work:

const (
	TYPE = "type"
)

type Shape struct {
	Type string fmt.Sprintf("json:\"%s\"", TYPE)
}

In the first example, I am using a string literal, which works. In the second example, I am building a string using fmt.Sprintf, and I seem to be getting an error:
syntax error: unexpected name, expecting }

Here it is on the Go playground:
https://play.golang.org/p/lUmylztaFg

答案1

得分: 9

在Go语言的结构标签中,你不能直接使用变量。这是由于Go语言不允许在结构标签中使用运行时求值的语句,而只能使用编译时的字符串字面量作为结构字段的注解。据我所知,任何编译型语言都不支持这样的功能。

英文:

How would I use a variable in a Go struct tag? You wouldn't, it's not allowed by the language. You can't use a statement that evaluates at runtime in place of a compile time string literal for as an annotation to a field on a struct. As far as I know nothing of the sort works in any compiled language.

答案2

得分: 3

通过引入go generate,可以实现这一点。

然而,go generate本质上使得编译成为一个两阶段的过程。第一阶段生成新的代码,第二阶段进行编译和链接等操作。

使用go generate存在一些限制:

  1. 除非每次需要时都运行go generate并检查结果,否则你的库将无法通过go get获取,因为go generate需要在go build之前显式运行。
  2. 这是一个编译时的过程,因此你将无法在运行时使用运行时信息来执行此操作。如果你确实必须在运行时执行此操作,并且在你的情况下,你只是添加JSON序列化注释,你可以考虑使用一个映射。
英文:

With the introduction of go generate, it is possible to do achieve this.

However, go generate essentially makes the compilation a 2 phase process. Phase 1 generates the new code, phase 2 compiles and links etc.

There are a few limitations with using go generate:

  1. Your library will not be 'go get'-able unless you run go generate every time it is needed and check in the result, since go generate needs to be explicitly run before go build
  2. This is a compile time process, so you will not be able to do it at run time using run time information. If you really must do this at run time, and in your case, you are just adding JSON serialization annotations, you could consider using a map.

答案3

得分: 1

字符串常量/变量不允许在标签值中使用[to keep things simple],我支持这一点。然而,由于这个限制,我们需要使用反射来检索标签值,这是昂贵的,或者在项目中到处使用类型字符串字面量,这可能会因为拼写错误而导致错误。

解决方案

我们可以将标签值生成为字符串常量,然后在项目中进一步使用这个常量。它不使用反射(节省性能开销),更易于维护,并消除了因为拼写错误而导致的任何错误的可能性。

ast包是一个很棒的工具,用于分析和生成Go代码。例如 -

type user struct {
    Name string `json:"name"`
    Age int `json:"age"`
}

我们可以为user结构生成如下的常量 -

const (
	UserNameJson = "name"
	UserAgeJson  = "age"
)

你可能会发现tgcon对于生成字段标签值作为常量很有帮助。

英文:

String const/variable is not allowed in tag value to keep things simple and I support that. However with this limit, we need to use reflection to retrieve the tag value which is costly OR type string literals everywhere in the project, which may lead to bugs because of typos.<br>

Solution

We can generate the tag values as string constant and then use this constant further in the project. It doesn't use reflection(saves performance cost), is more maintainable and removes the possibility of any bug because of typos.

ast package is an amazing tool to analyse and generate the go code. For example -

type user struct {
    Name string `json:&quot;name&quot;`
    Age int `json:&quot;age&quot;`
}

We can generated constants for user struct as below -

const (
	UserNameJson = &quot;name&quot;
	UserAgeJson  = &quot;age&quot;
)

You may find tgcon helpful to generate the field tag value as const.

huangapple
  • 本文由 发表于 2015年4月20日 23:46:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/29752462.html
匿名

发表评论

匿名网友

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

确定