Jak złamać długą linię kodu w Golangu?

108

Pochodzę z Pythona, nie jestem przyzwyczajony do oglądania linii kodu dłuższych niż 80 kolumn. Więc kiedy się z tym spotykam:

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

Próbowałem to złamać

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

Ale rozumiem

 syntax error: unexpected \

Spróbowałem też po prostu przełamać linię wciskając Enter i wstawić na końcu średnik:

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

Ale znowu otrzymuję:

syntax error: unexpected .

Zastanawiam się więc, jaki jest golangiczny sposób, aby to zrobić?

Karlom
źródło

Odpowiedzi:

122

Najpierw trochę tła. Formalna gramatyka Go używa średników ";"jako terminatorów w wielu produkcjach, ale programy Go mogą pomijać większość z nich (i powinny mieć jaśniejsze, łatwe do odczytania źródło; gofmtusuwa również niepotrzebne średniki).

Specyfikacja zawiera dokładne zasady. Specyfikacja: Średniki:

Gramatyka formalna używa średników ";" jako terminatory w wielu produkcjach. Programy Go mogą pomijać większość tych średników, korzystając z następujących dwóch reguł:

  1. Gdy dane wejściowe są podzielone na tokeny, średnik jest automatycznie wstawiany do strumienia tokenów natychmiast po ostatnim tokenie wiersza, jeśli ten token jest

  2. Aby umożliwić złożonym instrukcjom zajmowanie jednego wiersza, przed zamykającym „)” lub „}” można pominąć średnik.

Jak więc widzisz, wstawiając znak nowej linii po nawiasie ), średnik ;zostanie wstawiony automatycznie, a więc następny wiersz nie będzie traktowany jako kontynuacja poprzedniego wiersza. Tak właśnie stało się w twoim przypadku, więc następna linia zaczynająca się od .Scan(&ReadUser.ID,...da ci błąd w czasie kompilacji, ponieważ ta stojąca sama (bez poprzedniej linii) jest błędem kompilacji:syntax error: unexpected .

Możesz więc przerwać linię w dowolnym momencie, co nie jest sprzeczne z zasadami wymienionymi w punkcie 1.powyżej.

Zazwyczaj można złamać swoje linie po przecinku ,, po otwarcie nawiasie np (, [, {, i po kropce ., które mogą być odnoszącego się do pola lub metody pewnej wartości. Możesz również podzielić linię po operatorach binarnych (tych, które wymagają 2 operandów), np:

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

Jedną rzeczą wartą odnotowania jest to, że jeśli masz strukturę, wycinek lub literał mapy wymieniający początkowe wartości i chcesz przerwać wiersz po wypisaniu ostatniej wartości, musisz wstawić obowiązkowy przecinek, ,nawet jeśli jest to ostatnia wartość i nie nastąpi więcej, np .:

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

Ma to na celu zapewnienie zgodności z regułami dotyczącymi średników, a także umożliwia zmianę kolejności i dodawanie nowych wierszy bez konieczności zajmowania się dodawaniem / usuwaniem ostatniego przecinka; np. możesz po prostu zamienić 2 wiersze bez konieczności ich usuwania i dodać nowy przecinek:

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

To samo dotyczy wypisywania argumentów do wywołania funkcji:

fmt.Println("first",
    "second",
    "third",       // Note it ends with a comma
)
icza
źródło
3
Ciągle umieszczam przecinek na końcu literałów javascript. #hatejs
Paulo Scardine
27
TL; DR: Zwykle możesz łamać linie po przecinku, po otwierającym nawiasie np. (, [, {I po kropce., Która może odnosić się do pola lub metody o jakiejś wartości.
Peeter Kokk
2
Konieczność dodania dodatkowego przecinka na końcu przypomina mi kilka starych błędów IE js, okropne
Christophe Roussy
4
@ChristopheRoussy To subiektywne, z jednej strony uwielbiam, że wszystkie wiersze muszą kończyć się przecinkiem i mogę z łatwością przestawiać i dodawać nowe wiersze bez konieczności dodawania / usuwania przecinków.
icza
@icza, też lubię, gdy kończą się przecinkiem, ale nie muszę tego robić na koniec :)
Christophe Roussy
22

Najprostszym sposobem jest po prostu pozostawienie operatora ( .) w pierwszej linii.

\ kontynuacje linii są również odradzane w wielu przewodnikach w stylu Pythona, możesz zawinąć całe wyrażenie w parens, jeśli poruszasz się tam iz powrotem między go i pythonem, ponieważ ta technika działa w obu językach.

tobyodavies
źródło
Niezła wskazówka, jak zostawić operatora na końcu. Zadziałało.
Karlom
1
zawijanie w nawiasach nie działa w go afaik. Idź, nadal wstaw średnik w nawiasach
Adrian Shum
Właśnie spróbowałem i Go naprawdę wstawia niewidoczny średnik, nawet w nawiasach. Więc to działa tylko w Pythonie, a nie w Go.
Roland Illig
@RolandIllig To zdecydowanie działa: play.golang.org/p/oFKaxLTphU
tobyodavies
Przepraszam za moje sformułowanie, odnosiłem się do użycia nawiasów (ale tego nie napisałem). Zawijanie wyrażenia w nawiasach może działać w Pythonie, ale nie działa w Go.
Roland Illig
16

To kwestia stylu, ale lubię:

err := database.QueryRow(
    "select * from users where user_id=?", id,
).Scan(
    &ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email,
)
peterSO
źródło
16

Jak wspomniano, jest to kwestia preferencji stylu. Rozumiem, że twórcy Go zasugerowali styl oparty na swoim doświadczeniu, z którego się uczę, ale także zachowuję część mojego stylu z mojego doświadczenia.

Poniżej jest, jak bym to sformatował:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )
halor
źródło