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

108

Исходя из 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 .

Итак, мне интересно, как это сделать с помощью голанги?

Карлом
источник

Ответы:

122

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

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

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

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

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

Итак, как вы можете видеть, если вы вставляете символ новой строки после круглой скобки ), точка с запятой ;будет вставлена ​​автоматически, и поэтому следующая строка не будет рассматриваться как продолжение предыдущей. Это то, что произошло в вашем случае, и поэтому следующая строка, начинающаяся с .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
)
icza
источник
3
Я продолжаю ставить запятую в конце литералов javascript. #hatejs
Пауло Скардин
28
TL; DR: Обычно вы можете разбивать строки после запятой, после открытия скобок, например (, [, {, и после точки., Которая может ссылаться на поле или метод некоторого значения.
Пеэтер Кокк
2
Необходимость добавления дополнительной запятой в конце напоминает мне о некоторых старых ошибках IE js, ужасно
Кристоф Русси
4
@ChristopheRoussy Это субъективно, мне, например, нравится, что все строки должны заканчиваться запятой, и я могу легко переставлять и добавлять новые строки, не заботясь о добавлении / удалении запятых.
icza 05
@icza, мне тоже нравится, когда они заканчиваются запятой, но не нужно делать это для последней :)
Christophe Roussy
22

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

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

Tobyodavies
источник
Хороший совет о том, чтобы оставить оператора в конце. Это сработало.
Karlom
1
заключение в круглые скобки не работает в go afaik. Продолжайте вставлять точку с запятой в скобках
Адриан Шум
Я только что попробовал, и Go действительно вставляет невидимую точку с запятой даже внутри скобок. Так что это работает только в Python, а не в Go.
Роланд Иллиг,
@RolandIllig Это определенно работает: play.golang.org/p/oFKaxLTphU
tobyodavies
Извините за мою формулировку, я имел в виду использование круглых скобок (но не писал этого). Заключение выражения в круглые скобки может работать в Python, но не работает в Go.
Роланд Иллиг
16

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

err := database.QueryRow(
    "select * from users where user_id=?", id,
).Scan(
    &ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email,
)
Питер SO
источник
16

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

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

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )
галорий
источник