Skip to content

proposal: Go 2: string interpolation evaluating to string and list of expressions #50554

Closed as not planned
@Cookie04DE

Description

@Cookie04DE

Author background

  • Would you consider yourself a novice, intermediate, or experienced Go programmer?
    Experienced.
  • What other languages do you have experience with?
    Java, C#, Kotlin, JavaScript

Related proposals

  • Has this idea, or one like it, been proposed before?
    proposal: Go 2: string interpolation #34174 proposes string interpolation similar to other languages like C# and Kolin.
    • If so, how does this proposal differ?
      Instead of formatting on the language level I propose to add a language features that increases readability and maintainability but leaves the actual formatting up to the user's choosing.

Proposal

  • What is the proposed change?
    I propose to add "format strings" which are expressions that return a string and []interface{}. They are intended to be used with fmt.Printf and friends. They accept expressions and return the string without the expressions and the results of those in a slice in the order they appeared in.

  • Who does this proposal help, and why?
    Consider the following example:
    emailBody := fmt.Sprintf("Hello %s. The item %s you bookmarked on %s is available now. Consider purchasing now (%v) since there are only %d left.", name, product, date, whatever, amount)
    Can you tell at a glance which expression would go inside the brackets?
    If you can: Great; but I would expect many people to take longer.
    Now what if we wanted to change the email? Imagine we wanted the bracket and content to be at the end of the message. Now we have to change the actual string but also take care to remove the correct expression on the right and place it at the end; we have to change two places and keep them in sync. This adds cognitive overhead and is an easy source of bugs (although the tooling helps here).
    Consider how the email looks with the new syntax:
    emailBody := fmt.Sprintf($"Hello %s{name}. The item %s{product} you bookmarked on %s{date} is available now. Consider purchasing now (%v{whatever}) since there are only %d{amount}} left")
    Moving the brackets and content is very easy now and you can tell quickly what gets printed here.

  • Please describe as precisely as possible the change to the language.
    I propose to add the following new Go expression: $""
    The runes between the two quotation marks are to be treated like a string inside the regular quotation marks ("") with the exception of the opening and closing curly braces ({ and }). In between those there has to be a valid Go expression that evaluates to a single value (statements aren't allowed).
    If a literal open or closed curly bracket is needed the following two escape sequences are usable: \{ and \}. These are invalid anywhere else.
    I call these formatting strings (FS's for short).
    FS's are expressions that can be either be passed as arguments to a function or be assigned to variables.
    As function arguments:
    The function has to have the following two types as its parameters where the FS is inserted: string and []interface{} or string and ...interface{}. If the last parameter is variadic the FS has to be the last argument and no further may follow.
    As variable assignment:
    The FS has to be assigned to two variables of the following types: string and []interface{}.

The returned string contains everything inside the quotation marks besides the curly brackets and their contents. For example: For $"Hi, I am %s{name} and %d{age} years old" it is "Hi, I am %s and %d years old", while the slice contains the values of name and age.
The slice is never nil but can be empty if no expressions were provided.

  • What would change in the language spec?
    It would include the new quotation marks, the two types they evaluate to and explain in which contexts they may be used. As well as the requirements for their use in arguments and variable assignments.
    But most importantly it wouldn't need to even mention the fmt package, since the actual formatting isn't done by the language itself. This also adds flexibility since the processing code doesn't need to be the fmt package.
    Take this sql statement as an example: dbConn.QueryContext(context.Background, $"SELECT name FROM app_user WHERE email = $1{email} AND profile_type = $2{profileType}").
  • Please also describe the change informally, as in a class teaching Go.
    Instead of manually writing the format for the sprintf family of functions, we can use format strings which help maintain readability and are easier to modify. They behave just like normal strings with the exception that you can add expressions inside curly braces in them. Because the expressions are right next to where they are used you can easily copy and paste or move them without worrying about accidentally affecting the other expressions.
  • Is this change backward compatible?
    Yes.
    • Before
      fmt.Printf("Hello Gopher %s, you are %d years old and you're favorite food is %s", name, age, favoriteFood)
    • After
      fmt.Printf($"Hello Gopher %s{name}, you are %d{years} old and you're favorite food is %s{favoriteFood}")
  • Orthogonality: how does this change interact or overlap with existing features?
    There are no such features at language level.

Costs

  • Would this change make Go easier or harder to learn, and why?
    It would make Go slightly harder to learn since every new feature has to be learned and understood.
  • What is the cost of this proposal? (Every language change has a cost).
    The cost is the added complexity in the compiler and the tooling.
  • How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
    All of them, since the change introduces new syntax which need to be recognized. Gofmt also needs to format the expressions inside the curly braces.
  • What is the compile time cost?
    The compiler needs to be able to recognize the new quotes and treat the text inside the curly braces as Go expressions instead of pure text.
  • What is the run time cost?
    There is no extra runtime cost since the functionality is identical to the existing way.
  • Can you describe a possible implementation?
    Since the new syntax is merely cosmetic a transpiler could simply convert it to the old one and compile the result with the current compiler similar to how generic code was handled previously.
  • Do you have a prototype? (This is not required.)
    https://github.com/Cookie04DE/gof

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions