Avatar ·

Как писать многострочные строки в Go?

Всем привет! Я только начал изучать Go и столкнулся с проблемой при работе с длинными строками. Мне нужно сохранить SQL-запрос в переменную, но он занимает несколько строк. В Python я привык использовать тройные кавычки, но в Go такой синтаксис не работает. Вот что я пытаюсь сделать: ```go query := "SELECT id, name, email FROM users WHERE active = true ORDER BY name" ``` Компилятор выдаёт ошибку: `syntax error: unexpected newline in string literal`. Я пробовал использовать конкатенацию строк через `+`, но это выглядит громоздко: ```go query := "SELECT id, name, email " + "FROM users " + "WHERE active = true " + "ORDER BY name" ``` Также я слышал про "raw strings" с обратными кавычками, но не уверен, как они работают. Есть ли в Go более элегантный способ писать многострочные строки? Как правильно работать с длинными текстами, особенно когда нужно сохранить форматирование, например, для JSON или SQL-запросов? Буду благодарен за примеры и объяснения! <<>>

Raw strings (необработанные строки) — основной способ

В Go для многострочных строк используется синтаксис с обратными кавычками (backticks). Это так называемые "raw strings" (необработанные строки), которые позволяют писать текст на нескольких строках без экранирования. Все символы внутри таких строк интерпретируются буквально, включая переводы строк.

query := `SELECT id, name, email 
FROM users 
WHERE active = true 
ORDER BY name`

Этот код будет работать корректно. Обратите внимание на несколько важных моментов:

  • Переводы строки сохраняются в строке как символы \n
  • Обратные слэши (\) не экранируются — они остаются как есть
  • Кавычки внутри строки можно использовать без экранирования
  • Нельзя использовать обратные кавычки внутри такой строки (их нужно заменять или экранировать)

Примеры использования raw strings

JSON-данные:

jsonData := `{
    "name": "Alice",
    "age": 30,
    "city": "Moscow"
}`

HTML-шаблоны:

html := `<div class="container">
    <h1>Hello, World!</h1>
    <p>This is a multiline string in Go.</p>
</div>`

Проблема с отступами

Raw strings сохраняют все пробелы и табуляции. Если вы пишете многострочную строку внутри функции с отступами, эти отступы тоже попадут в строку:

func main() {
    query := `SELECT * 
               FROM users`  // Здесь будут лишние пробелы
    fmt.Println(query)
    // Выведет: SELECT * 
    //                FROM users
}

Чтобы избежать этого, можно выравнивать строку по левому краю или использовать обрезание пробелов:

func main() {
    query := `SELECT * 
FROM users`  // Просто переносим на новую строку без отступа
    fmt.Println(query)
}

Когда использовать raw strings, а когда — обычные

  • Raw strings (обратные кавычки): для SQL, JSON, HTML, документации, конфигураций — везде, где нужны многострочные строки и не требуется экранирование
  • Обычные строки (двойные кавычки): для коротких строк, где нужно экранирование (\n, \t, \") или интерполяция (хотя в Go нет встроенной интерполяции, только через fmt.Sprintf)

Конкатенация как альтернатива

Если вам нужно объединить строки с разным форматированием или добавить динамические части, можно использовать конкатенацию или strings.Builder:

query := "SELECT id, name, email " +
    "FROM users " +
    "WHERE active = true " +
    "ORDER BY name"

Этот подход тоже рабочий, но менее удобный для длинных текстов.

Важные ограничения raw strings

  • Нельзя использовать обратные кавычки внутри raw string. Если они нужны, используйте конкатенацию: `строка с ` + "`" + `кавычкой`
  • Raw strings не поддерживают escape-последовательности. Например, \n внутри raw string — это два символа (обратный слэш и n), а не перевод строки
  • Для интерполяции переменных нужно использовать fmt.Sprintf или конкатенацию

Вывод: для большинства случаев с многострочными строками в Go используйте raw strings с обратными кавычками. Это самый простой и читаемый способ.

<<>>

Альтернативный подход: strings.Builder для динамических строк

Если вам нужно собирать многострочную строку из частей, особенно с динамическими данными, лучше использовать strings.Builder. Это эффективнее, чем конкатенация через +, особенно для большого количества строк.

import "strings"

func buildQuery(table string, active bool) string {
    var sb strings.Builder
    sb.WriteString("SELECT id, name, email\n")
    sb.WriteString("FROM ")
    sb.WriteString(table)
    sb.WriteString("\n")
    if active {
        sb.WriteString("WHERE active = true\n")
    }
    sb.WriteString("ORDER BY name")
    return sb.String()
}

Этот подход даёт больше гибкости: вы можете добавлять условия, менять порядок строк и вставлять переменные. Кроме того, strings.Builder минимизирует выделение памяти, так как заранее выделяет буфер.

Также можно использовать fmt.Sprintf для форматирования, но для многострочных строк это менее удобно:

query := fmt.Sprintf("SELECT id, name, email\nFROM %s\nWHERE active = %t\nORDER BY name", table, active)

Для простых статических многострочных строк raw strings — лучший выбор. Для динамических — strings.Builder или fmt.Sprintf.