You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Go's struct tags has been wildly successful. It has been so successful, in fact, that many projects leverage the reflect.StructTag system to support code generation, struct value validation, storage and retrieval, UI presentation, and a number of other use cases. Tagging allows one structure to be used throughout the layers of the program resulting in having a central location to modify the attributes, yet also allowing customizations to be applied to each of the layers.
The following example is a use case where the struct is used to:
Generate a presentation layer (label, description)
Generate REST API docs (label, description, json, example, pattern)
Deserialize and validate data coming into a REST API (json, pattern)
Define how to persist the data in a SQL database (sql)
Serialize a response back to the client (json)
All of that meta information together could easily be as complicated as the following:
type Machine struct {
ID string `json:"id" yaml:"id" description:"UUID auto-generated to identify the machine" pattern:"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}" sql:"type:varchar(36);not null;unique;primary_key" label:"Machine Id" example="1328149e-15a1-11eb-adc1-0242ac120002"`
Host string `json:"host,omitempty" yaml:"host,omitempty" pattern:"(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])" description:"Host name for the machine" label:"Host Name" example:"myserver.domain.com" sql:"type:varchar(255)"`
IPv4 string `json:"ipv4,omitempty" yaml:"ipv4,omitempty" pattern:"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}" description:"IPv4 address for the machine." label:"IPv4 Address" example:"127.0.0.1" sql:"type:varchar(15)"`
}
Proposal
To improve readability, reduce mistakes, and allow the meta information to continue to scale, a minor backwards compatible change could be applied to the struct tag spec: allow newlines and tabs to exist within the tag. This would enable the following struct definition:
type Machine struct {
ID string `
label:"Machine ID"
description:"UUID auto-generated to identify the machine"
json:"id"
yaml:"id"
pattern:"[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"
example="1328149e-15a1-11eb-adc1-0242ac120002"
sql:"type:varchar(36);not null;unique;primary_key"
`
Host string `
label:"Host Name"
description:"Host name for the machine"
json:"host,omitempty"
yaml:"host,omitempty"
pattern:"(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])"
sql:"type:varchar(255)"
`
IPv4 string `
label:"IPv4 Address"
description:"IPv4 address for the machine"
json:"ipv4,omitempty"
yaml:"ipv4,omitempty"
pattern:"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}"
sql:"type:varchar(15)"
`
}
The resulting structure is much more readable and can help prevent mistakes (ironically, just converting the above example into the more readable format exposed my own mistake of missing an end quote). This allowance would still be backwards compatible with all previous tag definitions. In addition, denoting multi-line content with `` is already a well understood and widely used pattern in the Go community. This would be a natural fit that some probably already expect to work.
These new characters should only be allowed in the spaces between the key:"value" pairs. This would be consistent with the documentation on StructTag:
// A StructTag is the tag string in a struct field.
//
// By convention, tag strings are a concatenation of
// optionally space-separated key:"value" pairs.
// Each key is a non-empty string consisting of non-control
// characters other than space (U+0020 ' '), quote (U+0022 '"'),
// and colon (U+003A ':'). Each value is quoted using U+0022 '"'
// characters and Go string literal syntax.
Dependencies
The Go formatter would need to enforce a style for multi-line tags
@ianlancetaylor Yes, it does look like a dup of #38641 (which seems also to have gone through some evolutions & discussions and was eventually closed).
I think that seeing the recurrence and popularity of these, improved struct tags would be a popular improvement to Go language, even though it is not clear exactly how this could be done. Perhaps a meta-issue would be useful?
Overview
Go's struct tags has been wildly successful. It has been so successful, in fact, that many projects leverage the
reflect.StructTag
system to support code generation, struct value validation, storage and retrieval, UI presentation, and a number of other use cases. Tagging allows one structure to be used throughout the layers of the program resulting in having a central location to modify the attributes, yet also allowing customizations to be applied to each of the layers.The following example is a use case where the struct is used to:
All of that meta information together could easily be as complicated as the following:
Proposal
To improve readability, reduce mistakes, and allow the meta information to continue to scale, a minor backwards compatible change could be applied to the struct tag spec: allow newlines and tabs to exist within the tag. This would enable the following struct definition:
The resulting structure is much more readable and can help prevent mistakes (ironically, just converting the above example into the more readable format exposed my own mistake of missing an end quote). This allowance would still be backwards compatible with all previous tag definitions. In addition, denoting multi-line content with `` is already a well understood and widely used pattern in the Go community. This would be a natural fit that some probably already expect to work.
These new characters should only be allowed in the spaces between the
key:"value"
pairs. This would be consistent with the documentation onStructTag
:https://golang.org/src/reflect/type.go?s=30914:30935#L1101
Dependencies
Related:
The text was updated successfully, but these errors were encountered: