Come rompere una lunga fila di codice a Golang?


108

Provenendo da Python, non sono abituato a vedere righe di codice più lunghe di 80 colonne. Quindi, quando incontro questo:

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

Ho provato a romperlo

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

Ma capisco

 syntax error: unexpected \

Ho anche provato a rompere la linea premendo Invio e inserendo un punto e virgola alla fine:

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

Ma di nuovo ottengo:

syntax error: unexpected .

Quindi mi chiedo qual è il modo golangico per farlo?

Risposte:


122

Prima alcuni retroscena. La grammatica formale di Go utilizza i punti ";"e virgola come terminatori in molte produzioni, ma i programmi Go possono ometterne la maggior parte (e dovrebbero avere una fonte più chiara e facilmente leggibile; gofmtrimuove anche i punti e virgola non necessari).

La specifica elenca le regole esatte. Spec: Punto e virgola:

La grammatica formale utilizza il punto e virgola ";" come terminatori in una serie di produzioni. I programmi Go possono omettere la maggior parte di questi punti e virgola utilizzando le due regole seguenti:

  1. Quando l'input viene suddiviso in token, un punto e virgola viene automaticamente inserito nel flusso di token immediatamente dopo il token finale di una riga se tale token è

  2. Per consentire a istruzioni complesse di occupare una singola riga, è possibile omettere un punto e virgola prima di un ")" o "}" di chiusura.

Quindi, come puoi vedere, se inserisci un carattere di nuova riga dopo la parentesi ), ;verrà inserito automaticamente un punto e virgola e quindi la riga successiva non verrà trattata come la continuazione della riga precedente. Questo è quello che è successo nel tuo caso, e quindi la riga successiva che inizia con .Scan(&ReadUser.ID,...ti darà un errore in fase di compilazione poiché questo stare da solo (senza la riga precedente) è un errore in fase di compilazione:syntax error: unexpected .

Quindi puoi interrompere la tua linea in qualsiasi punto che non sia in conflitto con le regole elencate al punto 1.sopra.

In genere si può rompere le linee dopo virgola ,, dopo l'apertura parentesi ad esempio (, [, {e, dopo un punto .che può essere riferimento a un campo o un metodo di un certo valore. Puoi anche interrompere la riga dopo gli operatori binari (quelli che richiedono 2 operandi), ad esempio:

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

Una cosa degna di nota qui è che se hai una struttura, una sezione o un letterale di mappa che elenca i valori iniziali e vuoi spezzare la linea dopo aver elencato l'ultimo valore, devi inserire una virgola obbligatoria ,anche se questo è l'ultimo valore e no ne seguiranno altri, ad esempio:

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

Questo per conformarsi alle regole del punto e virgola, e anche per poter riorganizzare e aggiungere nuove righe senza doversi occupare di aggiungere / rimuovere la virgola finale; ad esempio puoi semplicemente scambiare le 2 linee senza dover rimuovere e aggiungere una nuova virgola:

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

Lo stesso vale quando si elencano gli argomenti in una chiamata di funzione:

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

3
Continuo a mettere una virgola alla fine dei letterali javascript. #hatejs
Paulo Scardine

27
TL; DR: in genere è possibile spezzare le righe dopo la virgola, dopo aver aperto le parentesi, ad esempio (, [, {e dopo un punto. Che potrebbe fare riferimento a un campo o a un metodo di qualche valore.
Peeter Kokk

2
Dover aggiungere una virgola in più alla fine mi ricorda alcuni vecchi bug di IE js, terribili
Christophe Roussy,

4
@ChristopheRoussy È soggettivo, io per primo amo che tutte le righe debbano terminare con una virgola e posso riorganizzare e aggiungere nuove righe con facilità senza doversi occupare di aggiungere / rimuovere virgole.
icza

@icza, mi piace anche che finiscano con una virgola, ma non devo farlo per l'ultima :)
Christophe Roussy

22

Il modo più semplice è lasciare semplicemente l'operatore ( .) sulla prima riga.

\ le continuazioni di riga sono anche scoraggiate in molte guide di stile Python, potresti racchiudere l'intera espressione tra parentesi se ti muovi avanti e indietro tra go e python poiché questa tecnica funziona in entrambi i linguaggi.


Bel consiglio su come lasciare l'operatore alla fine. Ha funzionato.
Karlom

1
l'avvolgimento tra parentesi non funziona in go afaik. Vai ancora a inserire il punto e virgola tra parentesi
Adrian Shum

L'ho appena provato e Go inserisce davvero un punto e virgola invisibile, anche tra parentesi. Quindi funziona solo in Python, non in Go.
Roland Illig

@RolandIllig Funziona decisamente: play.golang.org/p/oFKaxLTphU
tobyodavies

Scusa per la mia formulazione, mi riferivo all'uso delle parentesi (ma non l'ho scritto). Racchiudere l'espressione tra parentesi può funzionare in Python, ma non funziona in Go.
Roland Illig

16

È una questione di stile, ma mi piace:

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

16

Come accennato, questa è una questione di preferenza di stile. Capisco che i creatori di Go abbiano suggerito uno stile basato sulla loro esperienza da cui imparo, ma conservo anche un po 'del mio stile dalla mia esperienza.

Di seguito è riportato come lo formatterò:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.