884

Does Go have anything similar to Python's multiline strings:

"""line 1
line 2
line 3"""

If not, what is the preferred way of writing strings spanning multiple lines?

Darshan Rivka Whittle
  • 32,989
  • 7
  • 91
  • 109
aeter
  • 11,960
  • 6
  • 27
  • 29

12 Answers12

1353

According to the language specification, you can use a raw string literal, where the string is delimited by backticks instead of double quotes.

`line 1
line 2
line 3`
Amin Shojaei
  • 5,451
  • 2
  • 38
  • 46
Mark Byers
  • 811,555
  • 193
  • 1,581
  • 1,452
  • 207
    As a side note: The 'raw quote' as it is called, does not parse escape sequences. It is therefor the string literal of choice to write regular expression patterns as they usually contain non-standard escape sequences that would make the Go compiler complain of not double-escaped. It keeps the patterns clean and relatively readable. – jimt Oct 29 '11 at 01:35
  • 13
    Need to be careful with this when using endline spaces though. For example if you put a space after `line 1` it will be invisible in your editor but present in the string. – Ory Band Jan 13 '15 at 12:40
  • 2
    @DanieleD That's a slight nonsequitur, but which dialect? Presumably mainly MySQL? http://stackoverflow.com/a/10574031 Note that by extension of the same argument, it's a pain for embedding markdown, or shell scripts (if you opt to use backtick in place of `$(abcd)`). – Ivan Vučica Jul 06 '16 at 17:59
  • check this post: https://steemit.com/programming/@elsanto/how-to-create-multiline-strings-in-golang – Sanx Aug 24 '17 at 12:40
  • @DanieleD What makes you say it's a pain for sql? I'm thinking about using it for some SQL queries, because I like to be able to copy and paste from my source code into other contexts. Is it that it doesn't parse escape sequences? – Kyle Heuton Apr 04 '18 at 19:43
  • 11
    @KyleHeuton: Presumably Daniele D is using the backtick character in his/her SQL queries (as MySQL users often do), and finds it painful to have to represent it as \` + "\`" + \` and break copy-and-pastability. – ruakh Nov 29 '18 at 21:55
  • 2
    If people are having issues with this for MySQL, note you can always set the session sql mode e.g. `SET SESSION sql_mode = 'ANSI_QUOTES';` which will `Treat " as an identifier quote character (like the backtick quote character) and not as a string quote character.` Then just make sure to use apostrophe `'` for string literals which every SQL database I've ever seen does. see https://dev.mysql.com/doc/refman/5.7/en/sql-mode.html#sqlmode_ansi_quotes – Davos Apr 08 '19 at 15:21
  • 1
    The down side to this is that if you're writing it inside indented code, tabs will be included in the string, and to get rid of them would make your code look ugly. Under such circumstances I would prefer to use Azeem's answer – Lost Crotchet Oct 01 '19 at 15:54
  • Watch out with using these with parentheses. If you get a `syntax error: unexpected newline, expecting comma or )` then consider if you have a multi-line string followed by a closing parenthesis `)` on a separate line. Because of go's automatic semi-colon statement termination, a `)` on a separate line will cause an error. The quickest solution is move the `)` up so it's not on a separate line (or you can end the previous line with a superfluous comma) – User Dec 13 '19 at 14:02
  • It can be used with string interpolation, too: `fmt.Sprintf(\`Hello %s no. %d%s\`, "World", 42, myvar)` – volkit Jul 21 '22 at 11:36
173

You can write:

"line 1" +
"line 2" +
"line 3"

which is the same as:

"line 1line 2line 3"

Unlike using back ticks, it will preserve escape characters. Note that the "+" must be on the 'leading' line - for instance, the following will generate an error:

"line 1"
+"line 2"
Sebastian Lenartowicz
  • 4,695
  • 4
  • 28
  • 39
mddkpp at gmail.com
  • 1,923
  • 1
  • 10
  • 2
  • 42
    This solution is not analogous to Python's multiline strings. It splits the string literal over multiple lines, but the string itself does not contain multiple lines. – Ben Butler-Cole Jun 25 '15 at 13:42
  • 3
    Since this preserves escape characters, new lines can be simply added with `\n` and is much easier to work with dynamic strings and such. If I am correct, the accepted answer really is for static strings in code to make it look pretty. – RisingSun Feb 02 '16 at 19:17
  • 2
    Wouldn't that be very inefficient as well? Let the string be 3x a 6 char sequence: 6 + 2*6 +3*6 = 36 chars allocated when optimal would be 18 (since strings are immutable, every time you add two string a new string is created with length of the two strings concatenated). – N0thing Jun 02 '16 at 03:43
  • @N0thing: if there is only string literals, there is no runtime differences as the compiler will optimize. But there is a small (microseconds, or even nanoseconds) difference in compile time. – dolmen Feb 01 '17 at 13:10
  • I believe this is the best way to get a multiline string literal with CRLF line endings – ldanilek Sep 20 '18 at 20:21
  • This works greatly on `fmt.Sprintf("very long dynamic string, such as SQL")` – coanor Dec 28 '18 at 02:25
  • For sake of precision, I think there's an error in the result string: it should be "line 1line 2line 3", with a space before the number 3. – think01 Mar 04 '20 at 10:51
63

Use raw string literals for multi-line strings:

func main(){
    multiline := `line 
by line
and line
after line`
}

Raw string literals

Raw string literals are character sequences between back quotes, as in `foo`. Within the quotes, any character may appear except back quote.

A significant part is that is raw literal not just multi-line and to be multi-line is not the only purpose of it.

The value of a raw string literal is the string composed of the uninterpreted (implicitly UTF-8-encoded) characters between the quotes; in particular, backslashes have no special meaning...

So escapes will not be interpreted and new lines between ticks will be real new lines.

func main(){
    multiline := `line 
by line \n
and line \n
after line`

    // \n will be just printed. 
    // But new lines are there too.
    fmt.Print(multiline)
}

Concatenation

Possibly you have long line which you want to break and you don't need new lines in it. In this case you could use string concatenation.

func main(){
    multiline := "line " +
            "by line " +
            "and line " +
            "after line"

    fmt.Print(multiline) // No new lines here
}

Since " " is interpreted string literal escapes will be interpreted.

func main(){
    multiline := "line " +
            "by line \n" +
            "and line \n" +
            "after line"

    fmt.Print(multiline) // New lines as interpreted \n
}
I159
  • 29,741
  • 31
  • 97
  • 132
47

From String literals:

  • raw string literal supports multiline (but escaped characters aren't interpreted)
  • interpreted string literal interpret escaped characters, like '\n'.

But, if your multi-line string has to include a backquote (`), then you will have to use an interpreted string literal:

`line one
  line two ` +
"`" + `line three
line four`

You cannot directly put a backquote (`) in a raw string literal (``xx\).
You have to use (as explained in "how to put a backquote in a backquoted string?"):

 + "`" + ...
Community
  • 1
  • 1
VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
16

Go and multiline strings

Using back ticks you can have multiline strings:

package main

import "fmt"

func main() {

    message := `This is a 
Multi-line Text String
Because it uses the raw-string back ticks 
instead of quotes.
`

    fmt.Printf("%s", message)
}

Instead of using either the double quote (“) or single quote symbols (‘), instead use back-ticks to define the start and end of the string. You can then wrap it across lines.

If you indent the string though, remember that the white space will count.

Please check the playground and do experiments with it.

rynop
  • 50,086
  • 26
  • 101
  • 112
ASHWIN RAJEEV
  • 2,525
  • 1
  • 18
  • 24
8

Creating a multiline string in Go is actually incredibly easy. Simply use the backtick (`) character when declaring or assigning your string value.

package main

import (
    "fmt"
)

func main() {
    // String in multiple lines
    str := `This is a
multiline
string.`
    fmt.Println(str + "\n")
    
    // String in multiple lines with tab
    tabs := `This string
        will have
        tabs in it`
    fmt.Println(tabs)
}
Bilal Khan
  • 119
  • 1
  • 9
5

You can put content with `` around it, like

var hi = `I am here,
hello,
`
liam
  • 341
  • 2
  • 5
  • 9
4

You have to be very careful on formatting and line spacing in go, everything counts and here is a working sample, try it https://play.golang.org/p/c0zeXKYlmF

package main

import "fmt"

func main() {
    testLine := `This is a test line 1
This is a test line 2`
    fmt.Println(testLine)
}
David
  • 887
  • 8
  • 7
3

you can use raw literals. Example

s:=`stack
overflow`
Prabesh P
  • 150
  • 4
3

For me, I need to use ` grave accent/backquote and just write a simple test

+ "`" + ...

is ugly and inconvenient

so I take a characterfor example: U+1F42C to replace it


a demo

myLongData := `line1
line2 aaa
line3
` // maybe you can use IDE to help you replace all ` to 
myLongData = strings.ReplaceAll(myLongData, "", "`")

Go Playground

Performance and Memory Evaluation

+ "`" v.s. replaceAll(, "", "`")

package main

import (
    "strings"
    "testing"
)

func multilineNeedGraveWithReplaceAll() string {
    return strings.ReplaceAll(`line1
line2
line3 aaa`, "", "`")
}

func multilineNeedGraveWithPlus() string {
    return `line1
line2
line3` + "`" + "aaa" + "`"
}

func BenchmarkMultilineWithReplaceAll(b *testing.B) {
    for i := 0; i < b.N; i++ {
        multilineNeedGraveWithReplaceAll()
    }
}

func BenchmarkMultilineWithPlus(b *testing.B) {
    for i := 0; i < b.N; i++ {
        multilineNeedGraveWithPlus()
    }
}

cmd

go test -v -bench=. -run=none -benchmem    see more testing.B

output

goos: windows
goarch: amd64
pkg: tutorial/test
cpu: Intel(R) Core(TM) i7-6700 CPU @ 3.40GHz
BenchmarkMultilineWithReplaceAll
BenchmarkMultilineWithReplaceAll-8    12572316      89.95 ns/op   24 B/op  1 allocs/op
BenchmarkMultilineWithPlus
BenchmarkMultilineWithPlus-8          1000000000   0.2771 ns/op    0 B/op  0 allocs/op
PASS
ok      tutorial/test   7.566s

Yes, The + "`" has a better performance than the other.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
Carson
  • 6,105
  • 2
  • 37
  • 45
  • That is going to be slow (unless you do it just once). It would be much better to use separate strings and concatenate, because the compiler is likely to do it at compile time between literal strings. – Alexis Wilke Feb 19 '22 at 02:44
  • 1
    Hi @Alexis Wilke, thanks for the heads up. It's much better than people who vote down and don't leave any comments. I added performance and memory evaluation to decide which one to use according to their needs. – Carson Feb 19 '22 at 11:17
1

For me this is what I use if adding \n is not a problem.

fmt.Sprintf("Hello World\nHow are you doing today\nHope all is well with your go\nAnd code")

Else you can use the raw string

multiline := `Hello Brothers and sisters of the Code
              The grail needs us.
             `
0

I use the + with an empty first string. This allows a somehow readable format and it works for const.

const jql = "" +
    "cf[10705] = '%s' and " +
    "status = 10302 and " +
    "issuetype in (10002, 10400, 10500, 10501) and " +
    "project = 10000"
ceving
  • 21,900
  • 13
  • 104
  • 178