Як розбити довгий рядок коду в Golang?


107

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

Тож мені цікаво, який голангічний спосіб це зробити?

Відповіді:


121

Спочатку деякий фон. Формальна граматика 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
}

Це має відповідати правилам крапки з комою, а також для того, щоб ви могли переставляти та додавати нові рядки, не дбаючи про додавання / видалення кінцевої коми; наприклад, ви можете просто поміняти місцями 2 рядки без необхідності видаляти та додавати нову кому:

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

Те саме стосується перерахування аргументів до виклику функції:

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

3
Я продовжую ставити кому в кінці літералів javascript. #hatejs
Пауло Скардін

26
TL; DR: Зазвичай ви можете розбивати свої рядки після коми ,, після відкриття дужок, наприклад (, [, {, і після крапки. Яка може посилатися на поле або метод певного значення.
Пітер Кокк,

2
Додавання зайвої коми в кінці нагадує мені деякі старі помилки IE js, жахливо
Крістоф Руссі

4
@ChristopheRoussy Це суб'єктивно, я люблю, що всі рядки повинні закінчуватися комою, і я можу легко переставляти та додавати нові рядки, не дбаючи про додавання / видалення коми.
icza

@icza, мені також подобається, щоб вони закінчувалися комою, але не потрібно робити це останньою :)
Крістоф Руссі

22

Найпростіший спосіб - просто залишити оператор ( .) на першому рядку.

\ Продовження рядків також не рекомендується застосовувати у багатьох посібниках стилю python. Ви можете обернути весь вираз в паренах, якщо рухаєтеся вперед і назад між go та python, оскільки цей прийом працює на обох мовах.


Гарна порада щодо залишення оператора в кінці. Це спрацювало.
Карлом

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,
)

16

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

Нижче наведено, як я форматую це:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.