Låt oss gå Kommandoradsprogram med Golang

Översikt

Go Language är ett spännande nytt språk som får stor popularitet av goda skäl. I den här handledningen lär du dig att skriva kommandoradsprogram med Go. Provprogrammet heter multi-git, och det låter dig utföra git-kommandon på flera arkiv samtidigt.

Snabb introduktion till Go

Go är ett open-source C-liknande språk som skapats på Google av några av de ursprungliga C och Unix hackarna, som motiverades av deras ogillar C ++. Det visar i Gos design, vilket gjorde flera oortodoxa val som att eliminera implementeringsarv, mallar och undantag. Go är enkel, pålitlig och effektiv. Dess mest utmärkande funktion är dess uttryckliga stöd för samtidig programmering via så kallade goroutiner och kanaler.

Innan du börjar dissekera provprogrammet följer du den officiella guiden för att göra dig redo för Go-utveckling.

Go är ett otroligt kraftfullt programmeringsspråk, lära allt från att skriva enkla verktyg för att bygga skalbara, flexibla webbservrar i hela vår kurs.

Multi-Git-programmet

Multi-Git-programmet är ett enkelt men användbart Go-program. Om du arbetar på ett team där kodbasen är uppdelad på flera git-repositorier behöver du ofta göra ändringar över flera arkiv. Det här är ett problem eftersom git har inget begrepp i flera repositorier. Allt kretsar kring ett enda förråd. 

Detta blir särskilt besvärligt om du använder grenar. Om du arbetar på en funktion som berör tre arkiv måste du skapa en filial i varje av dessa arkiv och kom ihåg att kolla, dra, tryck och slå samman alla samtidigt. Detta är inte trivialt. Multi-Git hanterar en uppsättning repositories och låter dig använda hela uppsättningen samtidigt. Observera att den nuvarande versionen av multi-git kräver att du skapar filialerna individuellt, men jag kan lägga till den här funktionen vid ett senare tillfälle.

Genom att undersöka hur multi-git implementeras, lär du dig mycket om att skriva kommandoradsprogram i Go.

Paket och import

Go-program är organiserade i paket. Multi-Git-programmet består av en enda fil som heter main.go. Överst i filen anges paketnamnet "huvud", följt av en lista med import. Importen är andra paket som används av multi-git.

paketets huvudsakliga import ("flag" "fmt" "log" "os" "strängar" "os / exec")

Fmt-paketet används till exempel för formaterad I / O som liknar C: s printf och scanf. Go stöder installation av paket från en mängd olika källor via att få kommando. När du installerar paket hamnar de i ett namnrymd under $ GOPATH miljöfaktor. Du kan installera paket från en mängd olika källor som GitHub, Bitbucket, Google-kod, Launchpad och till och med IBM DevOps-tjänster via flera vanliga versionskontrollformat som git, subversion, mercurial och basar.

Kommandoradsargument

Kommandoradsargument är en av de vanligaste formerna för att ge input till program. De är lätta att använda, låter dig springa och konfigurera programmet i en rad och ha bra parsing support på många språk. Kall dem kommandoraden "flaggor" och har flaggpaketet för att ange och analysera kommandoradsargument (eller flaggor). 

Vanligtvis analyserar du kommandoradsargument i början av ditt program och multi-git följer denna konvention. Ingångspunkten är main () fungera. De två första linjerna definierar två flaggor som heter "command" och "ignoreErrors". Varje flagga har ett namn, en datatyp, ett standardvärde och en hjälpsträng. De flag.Parse () samtal kommer att analysera den faktiska kommandoraden som skickas till programmet och kommer att fylla i de definierade flaggorna.

func main () command: = flag.String ("kommandot", "", "Git-kommandot") ignoreErrors: = flag.Bool ("ignorera-fel", felaktigt, "Fortsätt springa efter fel om sant") flagga .Parse ()

Det är också möjligt att få tillgång till odefinierade argument via flag.Args () fungera. Flaggor står för fördefinierade argument och "args" är obearbetade argument. De obearbetade argumenten är 0-baserade indexerade.

Miljövariabler

En annan vanlig form av programkonfiguration är miljövariabler. När du använder miljövariabler kan du köra samma program flera gånger i samma miljö, och alla körningar kommer att använda samma miljövariabler. 

Multi-Git använder två miljövariabler: "MG_ROOT" och "MG_REPOS". Multi-git är utformad för att hantera en grupp git repositories som har en gemensam förälder katalog. Det är "MG_ROOT". Förvarets namn anges i "MG_REPOS" som en kommaseparerad sträng. För att läsa värdet av en miljövariabel kan du använda os.Getenv () fungera.

 // Få klara repos från miljövariabler root: = os.Getenv ("MG_ROOT") om root [len (root) - 1]! = '/' Root + = "/" repo_names: = strings.Split .Getenv ("MG_REPOS"), ",")

Verifiering av arkivlistan

Nu när det hittades rotkatalogen och namnen på alla repositories, verifierar multi-git att varje förvar finns under rot och att det verkligen är ett git-repository. Kontrollen är lika enkel som att leta efter en .git-underkatalog för varje förrådskatalog.

Först definieras en rad strängar med namnet "repos". Då det iterates över alla repo namn och konstruerar en förvaringsväg genom att sammanfoga rotkatalogen och repo-namnet. Om [Os.Stat ()] () Samtal misslyckas för .git-underkatalogen, det loggar felet och avslutar. Annars läggs förvaringsvägen till repos array.

 var repos [] string // Verifiera alla repos existerar och är egentligen git repos (har .git sub-dir) för _, r: = range repo_namn path: = root + r _, err: = os.Stat "/.git") om err! = nil log.Fatal (err) repos = append (repos, path)

Go har en unik felhanteringsanläggning där funktioner ofta returnerar både ett returvärde och ett felobjekt. Kolla in hur os.Stat () returnerar två värden. I så fall används "_" platshållaren för att hålla det faktiska resultatet eftersom du bara bryr dig om felet. Go är mycket strikt och kräver att namngivna variabler används. Om du inte planerar att använda ett värde, ska du tilldela det till _ för att undvika kompileringsfel.

Utför Shell-kommandon

Vid denna tidpunkt har du din lista över förvaringsvägar där vi vill utföra kommandot git. Som du kommer ihåg fick vi kommandoraden git som ett enda kommandoradsargument (flagga) som heter "kommando". Detta måste delas upp i en rad komponenter (git-kommando, delkommando och alternativ). Hela kommandot som en sträng lagras också för visningsändamål.

 // Bryt git-kommandot i komponenter (behövs för att exekvera) var git_components [] sträng för _, komponent: = strängområden.Split (* kommando, "") git_components = append (git_components, component) command_string: = "git "+ * kommandot

Nu är du redo att iterera över varje förråd och genomföra kommandot git i var och en. Konstruktionen "för ..." slingan används igen. Först ändrar multi-gitts arbetsboken till den aktuella målrepo "r" och skriver ut git-kommandot. Sedan kör det kommandot med hjälp av exec.Command () funktionen och skriver ut den kombinerade utgången (både standardutgång och standardfel). 

Slutligen kontrollerar den om det uppstod ett fel vid körningen. Om det uppstod ett fel och ignoreErrors flaggan är falsk då multi-git bails ut. Anledningen till att eventuella ignorera fel är att ibland är det OK om kommandon misslyckas på vissa repos. Om du till exempel vill kolla in en filial kallad "cool feature" på alla arkiv som har denna filial, bryr du dig inte om kassan misslyckas i repositorier som inte har denna filial.

 för _, r: = range repos // Gå till repo-katalogen os.Chdir (r); // Skriv ut kommandot fmt.Printf ("[% s]% s \ n", r, command_string) // Utför kommandot, fel: = exec.Command ("git", git_components ...) .CombinedOutput () / / Skriv ut resultatet fmt.Println (sträng (ut)) // Bail ut om det fanns ett fel och INTE ignorera fel om err! = Nil &&! * IgnoreErrors os.Exit (1) fmt.Println ("Done . ")

Slutsats

Go är ett enkelt men ändå kraftfullt språk. Den är avsedd för storskalig systemprogrammering men fungerar också bra för små kommandoradsprogram. Go's minimal design är i stark kontrast till andra moderna språk som Skala och Rust som är mycket kraftfulla och väldesignade, men har en väldigt brant inlärningskurva. Jag uppmuntrar dig att försöka Gå och experimentera. Det är väldigt kul.