Skip to content

proposal: Go 2: indentable multiline strings #45472

Closed
@VinGarcia

Description

@VinGarcia

First a disclaimer, I don't think this proposal is appropriate for Go1.0 it would only make sense if we were planning on rehashing the syntax a little bit, but regardless I think it was important to share because it's something that can have practical benefits.

The Problem

When working with multiline strings we often have a dilemma:

  1. Identing it to match the surrounding indentation
  2. Not indenting it so we reduce the size of the string by having fewer whitespaces in it.

And both solutions are not ideal:

  1. Identing to match the identation does not use gofmt which means that the confusion between tabs or spaces comes back
    causing problems on merges (which is the problem that actually convinced me to share this idea).
  2. Not indenting breaks the abstraction of a function block and causes the programmers to feel that it's wrong, so this option is not often used even though it would be the less problematic option.

Please note that always using solution 2 doesn't solve the problem since it's hard to enforce it on other programmers, especially if I have just moved to a new company and the code was already written using the first method.

Proposed Syntactical Solution

With that problem in mind, I thought about a syntactical solution that would fix this problem and both reduce the number of whitespaces on the string and allow indentation to take place normally.

Note: In the example below note that I am not recommending specifically the use of the " character for this, we can use any character or combination of characters that makes sense.

func example() {
    exampleText := "Starting a multiline identable string
        "continuing the string
        "this is the final line of the string"

    // This should print "true":
    fmt.Println(exampleText == "Starting a multiline identable string\ncontinuing the string\nthis is the final line of the string")
}

In the example above the idea is that if the programmer doesn't terminate the string in the same line as it started it the compiler would interpret the end of the line as an actual \n character that was part of the string. Then it would ignore the beginning of the next line until it found another " character and then continue to parse the string until it found another line break or a quote " for ending the string.

Other slightly different forms of using this syntax would be:

func example() {
    exampleText1 := "start here
        "
        "continue here, after an empty line
        "" // end here just because I wanted the string to end in a \n

    exampleText2 := "
        "started on the previous line because I like
        "how the indentation looks like when I do it like this"
}

I would also expect the following code to cause a compilation error:

func example() {
    badExampleText := "start here and skip one line without any quotes...
    
        "end the string here" // Syntax error because of an unterminated multiline string
}

Expected Benefits

This idea should give us 3 benefits:

  1. Have fewer merge conflicts regarding whitespaces on multiline strings (very common on big queries)
  2. Have a better-looking code without growing the size of it with whitespaces
  3. Normalizing how Gophers should write multiline strings so that everyone's code looks the same.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions