Подтвердить что ты не робот

Как разбить длинную строку кода в Голанге?

Исходя из Python, я не привык видеть строки кода длиной более 80 столбцов. Поэтому, когда я сталкиваюсь с этим:

err := database.QueryRow("select * from users where user_id=?", id).Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)

Я попытался сломать его на

err := database.QueryRow("select * from users where user_id=?", id) \
    .Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)

Но я получаю

 syntax error: unexpected \

Я также попытался просто сломать линию, нажав enter и положив точку с запятой в конце:

err := database.QueryRow("select * from users where user_id=?", id) 
.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email);

Но я снова получаю:

syntax error: unexpected .

Так что мне интересно, что такое голангический способ сделать это?

4b9b3361

Ответ 1

Сначала немного фона. Формальная грамматика Go использует точки с запятой ";" как терминаторы во многих продуктах, но программы Go могут пропускать большинство из них (и они должны иметь более понятный, легко читаемый источник; gofmt также удаляет ненужные точки с запятой).

В спецификации перечислены точные правила. Spec: Точки с запятой:

Формальная грамматика использует точки с запятой ";" как терминаторы в ряде постановок. Программы Go могут пропускать большинство этих точек с запятой, используя следующие два правила:

  • Когда ввод разбит на токены, точка с запятой автоматически вставляется в поток токенов сразу после финального токена линии, если этот токен

  • Чтобы позволить сложным операторам занимать одну строку, точка с запятой может быть опущена до закрытия ")" или "}".

Итак, как вы можете увидеть, если вы введете символ новой строки после скобки ), точка с запятой ; будет вставлена ​​автоматически, и поэтому следующая строка не будет считаться продолжением предыдущей строки. Это то, что произошло в вашем случае, и поэтому следующая строка, начинающаяся с .Scan(&ReadUser.ID,..., даст вам ошибку времени компиляции, поскольку эта позиция сама по себе (без предыдущей строки) является ошибкой времени компиляции: syntax error: unexpected .

Таким образом, вы можете разбить свою линию в любой точке, которая не противоречит правилам, перечисленным в пункте 1. выше.

Обычно вы можете разбить свои строки после запятой ,, после открытия скобки, например. (, [, { и после точки ., которая может ссылаться на поле или метод некоторого значения. Вы также можете разбить свою строку после двоичных операторов (те, которые требуют 2 операнда), например:

i := 1 +
        2
fmt.Println(i) // Prints 3

Здесь стоит отметить, что если у вас есть строковый или срезовый список или список букв, перечисляющий начальные значения, и вы хотите разбить строку после перечисления последнего значения, вы должны поместить обязательную запятую ,, хотя это это последнее значение, и больше не последует, например:

s := []int {
    1, 2, 3,
    4, 5, 6,  // Note it ends with a comma
}

Это должно соответствовать правилам с запятой, а также для того, чтобы вы могли изменять и добавлять новые строки, не заботясь о добавлении/удалении последней запятой; например вы можете просто поменять две строки без необходимости удаления и добавления новой запятой:

s := []int {
    4, 5, 6,
    1, 2, 3,
}

То же самое применимо при перечислении аргументов для вызова функции:

fmt.Println("first",
    "second",
    "third",       // Note it ends with a comma
)

Ответ 2

Самый простой способ - просто оставить оператор (.) в первой строке.

\ Продолжение строк также не рекомендуется во многих руководствах по стилю python, вы можете обернуть все выражение в parens, если вы двигаетесь назад и вперед между go и python, поскольку этот метод работает на обоих языках.

Ответ 3

Это вопрос стиля, но мне нравится:

err := database.QueryRow(
    "select * from users where user_id=?", id,
).Scan(
    &ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email,
)

Ответ 4

Как уже упоминалось, это вопрос стиля предпочтений. Я понимаю, что создатели Go предложили стиль, основанный на их опыте, из которого я учусь, но при этом я сохранил свой собственный стиль.

Ниже я хотел бы отформатировать это:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )