Come strutturare un progetto Go

Come linguaggio, Go è stato realizzato per risolvere determinati problemi ma si è scoperto essere un'ottima soluzione per una vastissima tipologia di software.
Perché è importante la struttura di un progetto?
Quando si visita un repository o un progetto al quale vogliamo contribuire o sul quale dobbiamo lavorare, il primo scoglio che incontriamo è l’ubicazione dei file che ci servono.
Perché un progetto Go abbia successo, è necessario partire innanzitutto dalla sua struttura: può aiutare a muoversi nel codice, capire quali sono le parti più importanti e trovare i file importanti, senza dover iniziare una caccia al tesoro imprevista.
Inoltre, grazie a una buona struttura, sarà più facile organizzare nuove funzionalità, permettendo al codice di crescere in maniera ordinata.
La scelta di come predisporre un progetto dipende principalmente da due fattori: la tipologia di software e la scelte in fase di progettazione.
Analizziamo la struttura di una categoria di software in crescita tra gli sviluppatori che utilizzano Go: i tool da riga di comando.

Struttura per un tool da linea di comando Go
Vediamo quali sono i componenti e la struttura di un generico progetto per un software eseguibile da linea di comando.
La struttura è molto semplice, ma permette di osservare e apprezzare i vantaggi di una buona struttura di base.

Oltre ai classici file di descrizione (README) e di aiuto nello sviluppo (Makefile), troviamo altre due cartelle: cmd e app.
Nella cartella cmd/ troviamo le istruzioni (i comandi) che possiamo lanciare all’avvio.
Nella cartella app/ troviamo le logiche del programma per la funzionalità hello: il nostro codice sorgente e un file di test.
Nella root troviamo due ulteriori file: go.mod, che contiene le indicazioni per la gestione delle dipendenze del programma, e main.go che contiene l’entrypoint al tool.
Se fossimo sviluppatori incaricati di implementare un nuovo comando goodbye, dove lo aggiungeremmo? Senza molti dubbi lo inseriremmo nella cartella cmd/.
E il nostro codice Go? Probabilmente in una cartella con un nome significativo rispetto alla funzionalità, goodbye, insieme alle altre sorgenti.
Questa è la struttura di un semplicissimo tool da linea di comando, con due comandi e un singolo file codice hello. Una struttura chiara e semplice ci ha permesso di aggiungere un nuovo comando mantenendo leggibilità e ordine della struttura.

Se il progetto avesse riguardato un software differente, avremmo potuto cambiare leggermente la struttura per adeguarlo alle nostre esigenze.
Ad esempio, una libreria potrebbe non organizzare i file in cartelle ma mantenere tutte le sorgenti Go nella root e usare la nomenclatura dei file (es: client Elasticsearch in Go). In questo caso, nonostante una prima visione confusionaria, è possibile dedurre facilmente quali comandi sono implementati e quali no, senza dover cercare all’interno del progetto.

Risorse per approfondire
Se l’argomento ti interessa e vuoi approfondire, ci sono moltissime risorse a proposito:
-
talk del 2018 alla GopherCon di Kat Zien dal titolo How Do You Structure Your Go Apps
-
talk del 2017 alla GopherCon di Edward Muller dal titolo Go Anti-Patterns
-
talk del 2018 alla GopherCon Russia di Ashley McNamara e Brian Ketelsen dal titolo Go best pratices
-
la documentazione ufficiale sulla nomenclatura dei packages e dei file
-
numerosi articoli di blog, post su reddit, domande su stackoverflow, compreso un repository di esempio con molte cartelle e sottocartelle descritte in maniera molto dettagliata.