Qual è un modo sensato per impaginare un progetto Go [chiuso]


113

Ho un progetto go che sta iniziando a diventare più complesso e voglio disporre il filesystem in modo tale da ridurre il dolore.

Ci sono alcuni buoni esempi di ciò che ha senso?

Risposte:


132

Aggiornamento maggio 2013: la documentazione ufficiale è nella sezione " Organizzazione del codice "

Il codice Go deve essere conservato all'interno di un'area di lavoro .
Uno spazio di lavoro è una gerarchia di directory con tre directory alla radice:

  • src contiene i file sorgenti di Go organizzati in pacchetti (un pacchetto per directory),
  • pkg contiene oggetti pacchetto e
  • bin contiene comandi eseguibili.

Il go toolcostruisce pacchetti sorgente e monta i binari risultanti per l' pkge bindirectory.

La srcsottodirectory contiene tipicamente più repository di controllo della versione (come Git o Mercurial) che tracciano lo sviluppo di uno o più pacchetti sorgente.

bin/
    streak                         # command executable
    todo                           # command executable
pkg/
    linux_amd64/
        code.google.com/p/goauth2/
            oauth.a                # package object
        github.com/nf/todo/
            task.a                 # package object
src/
    code.google.com/p/goauth2/
        .hg/                       # mercurial repository metadata
        oauth/
            oauth.go               # package source
            oauth_test.go          # test source

Aggiornamento luglio 2014: vedere " Structuring Applications in Go " di Ben Johnson

L'articolo include suggerimenti come:

Separa il tuo binario dalla tua applicazione

la combinazione del main.gofile e della logica dell'applicazione nello stesso pacchetto ha due conseguenze:

  • Rende la mia applicazione inutilizzabile come libreria.
  • Posso avere solo un binario dell'applicazione.

Il modo migliore che ho trovato per risolvere questo problema è semplicemente utilizzare una cmddirectory " " nel mio progetto in cui ciascuna delle sue sottodirectory è un binario dell'applicazione.

camlistore/
  cmd/
    camget/
      main.go
    cammount/
      main.go
    camput/
      main.go
    camtool/
      main.go

Sviluppo guidato dalla libreria

Spostare il main.gofile fuori dalla tua root ti permette di costruire la tua applicazione dal punto di vista di una libreria. Il file binario dell'applicazione è semplicemente un client della libreria dell'applicazione.

A volte potresti volere che gli utenti interagiscano in più modi in modo da creare più binari.
Ad esempio, se disponi di un adderpacchetto " " che consente agli utenti di aggiungere numeri insieme, potresti voler rilasciare una versione della riga di comando oltre a una versione web.
Puoi farlo facilmente organizzando il tuo progetto in questo modo:

adder/
  adder.go
  cmd/
    adder/
      main.go
    adder-server/
      main.go

Gli utenti possono installare i file binari dell'applicazione "adder" con "go get" utilizzando i puntini di sospensione:

$ go get github.com/benbjohnson/adder/...

E voilà, il tuo utente ha installato " adder" e " adder-server"!

Non impazzire con i sottopacchetti

Di solito i tipi di progetto sono tutti molto correlati, quindi si adatta meglio dal punto di vista dell'usabilità e dell'API.
Questi tipi possono anche trarre vantaggio dalle chiamate non esportate tra di loro che mantiene l'API piccola e chiara.

  1. Raggruppa i tipi e il codice correlati in ogni file. Se i tipi e le funzioni sono ben organizzati, trovo che i file tendono ad essere compresi tra 200 e 500 SLOC. Potrebbe sembrare molto, ma trovo che sia facile da navigare. 1000 SLOC è solitamente il mio limite massimo per un singolo file.
  2. Organizza il tipo più importante all'inizio del file e aggiungi i tipi con importanza decrescente verso la fine del file.
  3. Una volta che la tua applicazione inizia a superare i 10.000 SLOC, dovresti valutare seriamente se può essere suddivisa in progetti più piccoli.

Nota: l'ultima pratica non è sempre buona:

Scusa, non sono d'accordo con questa pratica.
Separare il tipo dai file aiuta la gestione del codice, la leggibilità, la manutenibilità e la testabilità.
Può anche garantire una responsabilità unica e il rispetto del principio di apertura / chiusura ...
La regola per non consentire la dipendenza circolare è di forzare che abbiamo una struttura chiara dei pacchetti.


(Alternativa a febbraio 2013, srcsolo per quanto riguarda )
È possibile trovare il layout classico illustrato in " Layout codice GitHub ":

L'app ed entrambe le librerie vivono su Github, ciascuna nel proprio repository.
$GOPATHè la radice del progetto: ciascuno dei tuoi repository Github verrà estratto in diverse cartelle di seguito $GOPATH.

Il layout del codice sarebbe simile a questo:

$GOPATH/
    src/
        github.com/
            jmcvetta/
                useless/
                    .git/
                    useless.go
                    useless_test.go
                    README.md
                uselessd/
                    .git/
                    uselessd.go
                    uselessd_test.go
                    README.md

Ogni cartella sotto src/github.com/jmcvetta/è la radice di un checkout git separato.

Ciò ha però attirato alcune critiche, in questa pagina reddit :

Consiglio vivamente di non strutturare il repository come hai fatto, si romperà " go get", che è una delle cose più utili di Go.
È molto meglio scrivere il codice per le persone che conoscono Go, poiché è molto probabile che siano loro a compilarlo.
E per le persone che non lo fanno, almeno avranno un'idea della lingua.

Metti il ​​pacchetto principale nella radice del repository.
Avere le risorse in una sottodirectory (per mantenere le cose in ordine).
Conserva la sostanza del codice in un sottopacchetto (nel caso qualcuno volesse riutilizzarlo al di fuori del tuo binario).
Includere uno script di installazione nella radice del repository in modo che sia facile da trovare.

È ancora solo un processo in due fasi per scaricare, creare, installare e configurare:

  • " go get <your repo path>": scarica e installa il codice go, con una sottodirectory per le risorse
  • $GOPATH/<your repo path>/setup.sh: distribuisce le risorse nel posto giusto e installa il servizio

15
Un (grosso) problema setup.shè che Go è ragionevolmente multipiattaforma mentre gli script di shell POSIX non lo sono.
kostix

La struttura jmcvetta non si romperà go get, poiché inutile importa inutile, go get installerà entrambi con go get ... / uselessd. Ma sono d'accordo che se inutile è una libreria creata appositamente per inutile, ha più senso tenerla in un unico repository git, come sottocartella o fratelli.
mna

@PuerkitoBio sono d'accordo. La mia formazione nel controllo della versione e nella gestione basata sui componenti ( stackoverflow.com/a/933735/6309 ) mi porta più verso un componente per repo, da qui la seconda parte di questa risposta.
VonC

7

Presumo che con "progetto" non intendi un pacchetto Go ma un software che sviluppi. Altrimenti puoi ottenere aiuto qui e qui . Tuttavia non è molto diverso dallo scrivere pacchetti per Go: usa i pacchetti, crea una cartella per ogni pacchetto e combina quei pacchetti nella tua applicazione.

Per costruirti un'opinione, puoi guardare i repository Go di tendenza su github: https://github.com/trending/go . Esempi degni di nota sono Cayley e Zeus .

Lo schema più popolare è probabilmente quello di avere un file Go principale e molti moduli e sottomoduli nelle proprie directory. Nel caso tu abbia molti meta file (doc, licenza, modelli, ...) potresti voler mettere il codice sorgente in una sottodirectory. Questo è quello che ho fatto finora.


@aussiegeek, non sono un esperto di Go, ma ho applicato con successo ciò che nemo ha proposto nel mio codice: l'idea è che puoi avere moduli nella directory del tuo progetto, devi solo fare riferimento a loro usando il loro prefisso completo - relativo a $GOPATH/srco utilizzando i loro go getnomi -table.
kostix

doozerdnon è un buon esempio, anche i suoi test sono deboli.
Inanc Gumus

@InancGumus ti incoraggio a suggerire un esempio migliore.
nemo

vedere questo e questo .
Inanc Gumus

1

C'è un approccio consigliato dagli autori di Golang che definisce come impaginare il codice per lavorare al meglio con gli strumenti go e per supportare i sistemi di controllo del codice sorgente


1
Ecco come impaginare $GOROOT, non il codice all'interno della src/<project>directory.
docwhat

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.