De Go-taal is een opwindende nieuwe taal die om een goede reden veel populariteit verwerft. In deze zelfstudie leer je hoe je opdrachtregelprogramma's met Go kunt schrijven. Het voorbeeldprogramma wordt multi-git genoemd en het staat je toe om git-commando's tegelijkertijd op meerdere repositories uit te voeren.
Go is een open-source C-achtige taal gemaakt door een aantal van de oorspronkelijke C- en Unix-hackers, die gemotiveerd waren door hun afkeer van C ++. Het wordt weergegeven in het ontwerp van Go, dat verschillende onorthodoxe keuzes heeft gemaakt, zoals het veronachtzamen van overerving van de implementatie, sjablonen en uitzonderingen. Go is eenvoudig, betrouwbaar en efficiënt. Het meest onderscheidende kenmerk is de expliciete ondersteuning voor gelijktijdige programmering via zogenaamde goroutines en kanalen.
Voordat u begint met het ontleden van het voorbeeldprogramma, volgt u de officiële handleiding om u op Go-ontwikkeling voor te bereiden.
Go is een ongelooflijk krachtige programmeertaal, leer alles van het schrijven van eenvoudige hulpprogramma's tot het bouwen van schaalbare, flexibele webservers in onze volledige cursus.
Het multi-git-programma is een eenvoudig maar nuttig Go-programma. Als je in een team werkt waarbij de codebase verdeeld is over meerdere git-repositories, dan moet je vaak veranderingen aanbrengen in meerdere repositories. Dit is een probleem omdat git geen concept heeft van meerdere repositories. Alles draait om een enkele repository.
Dit wordt vooral lastig als u takken gebruikt. Als u werkt aan een functie die drie repositories raakt, moet u een featurentak in elk van deze repository's maken en vervolgens onthouden om ze allemaal uit te checken, te trekken, te pushen en samen te voegen op hetzelfde moment. Dit is niet triviaal. Multi-git beheert een set opslagplaatsen en laat je de hele set in één keer bedienen. Merk op dat de huidige versie van multi-git vereist dat je de takken afzonderlijk aanmaakt, maar ik kan deze functie op een later tijdstip toevoegen.
Door de manier waarop multi-git is geïmplementeerd te verkennen, leert u veel over het schrijven van opdrachtregelprogramma's in Go.
Go-programma's zijn georganiseerd in pakketten. Het multi-git-programma bestaat uit een enkel bestand met de naam main.go. Bovenaan het bestand wordt de pakketnaam 'main' opgegeven, gevolgd door een lijst met importen. De invoer is andere pakketten die door multi-git worden gebruikt.
pakket main import ("flag" "fmt" "log" "os" "strings" "os / exec")
Het fmt-pakket wordt bijvoorbeeld gebruikt voor geformatteerde I / O, vergelijkbaar met C's printf en scanf. Go ondersteunt het installeren van pakketten van verschillende bronnen via de ga halen
commando. Wanneer u pakketten installeert, komen ze terecht in een naamruimte onder de $ GOPATH omgevingsvariabele. U kunt pakketten van verschillende bronnen zoals GitHub, Bitbucket, Google-code, Launchpad en zelfs IBM DevOps-services installeren via verschillende veelgebruikte versiebeheer-indelingen zoals git, subversion, mercurial en bazaar..
Opdrachtregelargumenten zijn een van de meest voorkomende vormen van invoer van programma's. Ze zijn eenvoudig te gebruiken, stellen u in staat om het programma op één regel uit te voeren en te configureren en hebben geweldige parseerondersteuning in vele talen. Go noemt ze commandoregel-"vlaggen "en heeft het vlagpakket voor het specificeren en parseren van opdrachtregelargumenten (of vlaggen).
Meestal parseer je opdrachtregelargumenten aan het begin van je programma en volgt multi-git deze conventie. Het beginpunt is de hoofd()
functie. De eerste twee regels definiëren twee vlaggen, genaamd "command" en "ignoreErrors". Elke vlag heeft een naam, een gegevenstype, een standaardwaarde en een help-tekenreeks. De flag.Parse ()
oproep zal de eigenlijke commandolijn ontleden die aan het programma is doorgegeven en zal de gedefinieerde vlaggen vullen.
func main () command: = flag.String ("command", "", "The git command") ignoreErrors: = flag.Bool ("ignore-errors", false, "Blijf actief na fout als waar") flag .Parse ()
Het is ook mogelijk om toegang te krijgen tot ongedefinieerde argumenten via de flag.Args ()
functie. Vlaggen staan dus voor vooraf gedefinieerde argumenten en "args" zijn onbewerkte argumenten. De onbewerkte argumenten zijn op basis van 0 geïndexeerd.
Een andere veel voorkomende vorm van programmaconfiguratie is omgevingsvariabelen. Wanneer u omgevingsvariabelen gebruikt, mag u hetzelfde programma meerdere keren in dezelfde omgeving uitvoeren en zullen alle runs dezelfde omgevingsvariabelen gebruiken.
Multi-git maakt gebruik van twee omgevingsvariabelen: "MG_ROOT" en "MG_REPOS". Multi-git is ontworpen om een groep git-repositories te beheren die een gemeenschappelijke bovenliggende directory hebben. Dat is "MG_ROOT". De namen van de repository worden gespecificeerd in "MG_REPOS" als een door komma's gescheiden reeks. Om de waarde van een omgevingsvariabele te lezen, kunt u de os.Getenv ()
functie.
// Krijg beheerde repo's van omgevingsvariabelen root: = os.Getenv ("MG_ROOT") als root [len (root) - 1]! = '/' Root + = "/" repo_names: = strings.Split (os . Getenv ("MG_REPOS"), ",")
Nu dat het de root directory en de namen van alle repositories heeft gevonden, verifieert multi-git dat elke repository bestaat onder root en dat het echt een git repository is. De controle is zo simpel als het zoeken naar een .git-submap voor elke repository-directory.
Eerst wordt een reeks reeksen met de naam "repos" gedefinieerd. Vervolgens itereert het over alle repo-namen en wordt een repositorypad geconstrueerd door de hoofdmap en de repo-naam samen te voegen. Als het [Os.Stat ()] ()
oproep mislukt voor de submap .git, het logt de fout en verlaat het. Anders wordt het repository pad toegevoegd aan de repos array.
var repos [] string // Controleer of alle repos bestaan en zijn eigenlijk git repos (hebben .git sub-dir) voor _, r: = bereik repo_names pad: = root + r _, err: = os.Stat (pad + "/.git") if err! = nil log.Fatal (err) repos = append (repos, path)
Go heeft een unieke foutafhandelingsfaciliteit waarbij functies vaak zowel een geretourneerde waarde als een foutobject retourneren. Bekijk hoe os.Stat ()
retourneert twee waarden. In dit geval wordt de tijdelijke aanduiding "_" gebruikt om het werkelijke resultaat vast te houden, omdat u alleen om de fout geeft. Go is erg strikt en vereist dat benoemde variabelen worden gebruikt. Als u niet van plan bent om een waarde te gebruiken, moet u deze toewijzen aan "_" om een compilatiefout te voorkomen.
Op dit punt heb je je lijst met repository paden waar we de git-opdracht willen uitvoeren. Zoals je je herinnert, ontvingen we de git-opdrachtregel als een enkel commandoregelargument (vlag) genaamd "commando". Dit moet worden opgesplitst in een array van componenten (git-commando, sub-commando en opties). De hele opdracht als een tekenreeks wordt ook opgeslagen voor weergavedoeleinden.
// Breek de opdracht git in componenten (nodig om uit te voeren) var git_components [] string for _, component: = range strings.Split (* command, "") git_components = append (git_components, component) command_string: = "git "+ * commando
Nu bent u helemaal klaar om elke repository te itereren en de opdracht git in elk repository uit te voeren. De "voor ... bereik" -lusconstructie wordt opnieuw gebruikt. Ten eerste verandert multi-git de werkmap naar de huidige doel-repo "r" en wordt de opdracht git afgedrukt. Vervolgens voert het de opdracht uit met behulp van de exec.Command ()
functioneert en drukt de gecombineerde uitvoer af (zowel standaarduitvoer als standaardfout).
Ten slotte controleert het of er een fout was tijdens de uitvoering. Als er een fout is opgetreden en de ignoreErrors
vlag is onwaar dan wordt multi-git gered. De reden voor het optioneel negeren van fouten is dat het soms OK is als opdrachten bij sommige repo's mislukken. Als u bijvoorbeeld een filiaal met de naam "coole functie" wilt bekijken in alle archieven die deze tak hebben, maakt het u niet uit als de kassa mislukt op bibliotheken die deze tak niet hebben.
voor _, r: = bereik repos // Ga naar de repo's directory os.Chdir (r); // Print het commando fmt.Printf ("[% s]% s \ n", r, command_string) // Execute the command out, err: = exec.Command ("git", git_components ...) .CombinedOutput () / / Print het resultaat fmt.Println (string (out)) // Bail out als er een fout was en Fouten NIET negeren als err! = Nil &&! * IgnoreErrors os.Exit (1) fmt.Println ("Done . ")
Go is een eenvoudige maar krachtige taal. Het is ontworpen voor grootschalige systeemprogrammering, maar werkt ook prima voor kleine opdrachtregelprogramma's. Het minimale ontwerp van Go staat in schril contrast met andere moderne talen, zoals Scale en Rust, die ook erg krachtig en goed ontworpen zijn, maar een zeer steile leercurve hebben. Ik moedig je aan om Go te proberen en te experimenteren. Het is heel erg leuk.