Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a variable in the struct tag

Tags:

json

go

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

like image 896
egidra Avatar asked Apr 20 '15 15:04

egidra


People also ask

What are Golang struct tags?

In the Go programs, you can add an optional string literal to a struct field. This is known as a struct tag. It is used to hold meta-information for a struct field. You can then export the information in the field to other packages to execute an operation or structure the data appropriately.

What is a struct tag?

A struct is a user-defined type that contains a collection of fields. It is used to group related data to form a single unit. A Go struct can be compared to a lightweight class without the inheritance feature. A struct tag is additional meta data information inserted into struct fields.

What is Go tag?

Tags are a way to attach additional information to a struct field. The Go spec in the Struct types definition defines tags as. A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration.


3 Answers

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.

like image 158
evanmcdonnal Avatar answered Oct 01 '22 00:10

evanmcdonnal


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.
like image 30
Qian Qiao Avatar answered Sep 30 '22 22:09

Qian Qiao


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.

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:"name"`
    Age int `json:"age"`
}

We can generated constants for user struct as below -

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

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

like image 24
amarjeetAnand Avatar answered Oct 01 '22 00:10

amarjeetAnand