Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

proposal: Go 2: struct tag interpolation of constants #66108

Closed
1 of 4 tasks
chad-bekmezian-snap opened this issue Mar 4, 2024 · 5 comments
Closed
1 of 4 tasks

proposal: Go 2: struct tag interpolation of constants #66108

chad-bekmezian-snap opened this issue Mar 4, 2024 · 5 comments
Labels
LanguageChange Proposal Proposal-FinalCommentPeriod v2 A language change or incompatible library change
Milestone

Comments

@chad-bekmezian-snap
Copy link

Go Programming Experience

Intermediate

Other Languages Experience

Python, JS, C#, Java

Related Idea

  • Has this idea, or one like it, been proposed before?
  • Does this affect error handling?
  • Is this about generics?
  • Is this change backward compatible? Breaking the Go 1 compatibility guarantee is a large cost and requires a large benefit

Has this idea, or one like it, been proposed before?

It feels like it must've before, but I couldn't find anything like it.

Does this affect error handling?

No.

Is this about generics?

No.

Proposal

Go supports adding tags to struct fields. This feature has been frequently used in packages used for ORMs, unmarshalling, code generation, struct validation, and more. It is not uncommon to see multiple values provided under a given tag, such as the json tag, or validate tag. These values are often separated by a literal comma, and an equals sign is generally used more or less as an assignment operator. A common convention is also to have the first value associated with a given tag define the name of the field within the context of that tag. Here is a somewhat overloaded example of such tags:

type User struct {
   Age int `json:"age,string" db:"age" validate:"required,min=18,max=30" doc:",desc=some helpful documentation"`
}

In the case of interacting with a database, I have also found myself on occasion declaring a constant with the name of the db column, for example:
const ColAge = "age"

Another semi-common pattern I have found is the use of a characters hex value to avoid issues with parsing struct tag values. For example:

struct {
   Field string `doc:",desc=this is a description, but it includes a comma and therefore isn't properly parsed"`
}

Commonly used struct tag parsing packages end up extracting the Field doc tag into three parts, due to the comma within the description. The offered solution is typically something along the lines of using the hex representation of a comma 0x2C, which would look like this:

struct {
   Field string `doc:",desc=this is a description0x2C but it includes a comma and therefore isn't properly parsed"`
}

I propose adding language support for interpolating constants into struct fields, which would hopefully improve readability, and reduce repetition. I don't have a desired exact syntax in mind, beyond of course that it would need to be backwards compatible. With the addition of this feature, the above examples could look something like this:

const (
   ColAge = "age"

   comma = "0x2C"
)

struct {
   Age string `db:"$ColAge" doc:",desc=this is a description$comma but it includes a comma and therefore isn't properly parsed"`
}

Language Spec Changes

No response

Informal Change

This change would allow interpolating constants in struct tags. Something like this:

const (
   ColAge = "age"

   comma = "0x2C"
)

struct {
   Age string `db:"$ColAge" doc:",desc=this is a description$comma but it includes a comma and therefore isn't properly parsed"`
}

Is this change backward compatible?

I believe it could be with careful consideration.

Orthogonality: How does this change interact or overlap with existing features?

The improvement would be in code readability.

Would this change make Go easier or harder to learn, and why?

It would be harder due to having another feature to learn, but the learning curve is minute.

Cost Description

A change to the compiler to handle the additional syntax. I am not super familiar with the compiler's implementation, but I expect it would be easy.

Changes to Go ToolChain

go

Performance Costs

the compile time cost would exist, but should be small

Prototype

No response

@chad-bekmezian-snap chad-bekmezian-snap added LanguageChange Proposal v2 A language change or incompatible library change labels Mar 4, 2024
@gopherbot gopherbot added this to the Proposal milestone Mar 4, 2024
@seankhliao
Copy link
Member

Related proposal for structured tags #23637

@ianlancetaylor
Copy link
Contributor

This proposal is not backward compatible. It would change the meaning of existing struct tags that contain a $ character. While there are ways to mitigate that, a lack of backward compatibility requires a really significant benefit. We don't see that here. Therefore this is a likely decline. Leaving open for four weeks for final comments.

@chad-bekmezian-snap
Copy link
Author

This proposal is not backward compatible. It would change the meaning of existing struct tags that contain a $ character. While there are ways to mitigate that, a lack of backward compatibility requires a really significant benefit. We don't see that here. Therefore this is a likely decline. Leaving open for four weeks for final comments.

While the example syntax I provided may not be backwards compatible, I don’t think it should be very hard to figure out a backwards compatible syntax. For example, prefixing the entire struct tag with a dollar sign could be what sets it apart for the compiler, and then brackets can be used to interpolate the actual constant, like so:

const ColName =nametype User struct {
   Name string $`db:”{ColName}”`
}

I believe that syntax would be 100% backwards compatible

@ianlancetaylor
Copy link
Contributor

We've discussed a lot of these issues at #34174 and friends.

@ianlancetaylor
Copy link
Contributor

No change in consensus.

@ianlancetaylor ianlancetaylor closed this as not planned Won't fix, can't repro, duplicate, stale Apr 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
LanguageChange Proposal Proposal-FinalCommentPeriod v2 A language change or incompatible library change
Projects
None yet
Development

No branches or pull requests

4 participants