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


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

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

4 53

4 ответа:

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

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

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

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

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

так как вы можете видеть, если вы вставляете символ новой строки после скобки ), a точка с запятой ; будет вставлен автоматически, поэтому следующая строка не будет рассматриваться как продолжение предыдущей строки. Это то, что произошло в вашем случае, и поэтому следующая строка начинается с .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
}

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

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

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

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

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

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

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

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

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

ниже, как я бы этот формат: err := database. QueryRow("select * from users where user_id=?", id). Scan( &ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email, )