Introducció: La il·lusió de la simplicitat Probablement el tipus o A la superfície, aquests comandaments se senten gairebé màgics: pressiona Enter, i de sobte el seu codi es compila, enllaça i - de vegades - executa. Però sota aquesta senzillesa hi ha un sistema acuradament orquestrat, optimitzat per fer la seva vida com a desenvolupador més fàcil, mentre que també és ràpid i previsible per a les màquines. go build go run Comprendre com el Go gestiona la construcció, l'execució i la memòria cau del codi no és només un exercici acadèmic. Això explica per què les construccions incrementals són tan ràpides, per què les canonades de CI es comporten de manera coherent, i per què de vegades un canvi aparentment trivial pot desencadenar una recopilació completa. Al final, tindràs una imatge clara de: Com resoldre dependències i estructures del codi en paquets com la compilació i l'enllaç treballen darrere de les escenes, per què el caixer de construcció és tan fiable, i Què passa realment quan escrius go build o go run? Si alguna vegada t'has preguntat per què el Go construeix "només treball" o per què el teu Les binàries semblen gairebé instantànies, aquest és el submarinisme profund que connecta els punts, tant per a humans com per a màquines. go run El model mental de la Go Toolchain A primera vista, , , i semblen comandes separades, cadascuna amb el seu propi comportament. En realitat, només són frontends per al Cada comanda Go passa per una seqüència predictible: carrega mòduls, resol dependències de paquets, compila paquets, opcionalment els vincula a un executable, i de vegades executa el resultat. No és la mecànica de la construcció. go build go run go test same underlying pipeline what happens to the final artifact Un concepte clau per a la internacionalització és que Cada arxiu .go en un paquet es tracta col·lectivament, i el paquet mateix és la unitat que compila i construeix la pista de memòria cau. Go builds packages, not individual files La modificació d'un sol arxiu en un paquet pot desencadenar una reconstrucció de tot el paquet. Els paquets es converteixen en els límits naturals per al cache i la compilació paral·lela. Els paquets petits i enfocats tendeixen a escalar millor en bases de codi grans perquè el compilador pot reutilitzar més resultats en memòria cau. El pipeline és conceptualment simple, però altament optimitzat: Go sap exactament què necessita recompilació i què es pot reutilitzar, per la qual cosa les construccions incrementals se senten gairebé instantànies. Orquestra la compilació, l'enllaç, la memòria cau i l'execució, de manera que rarament has de preocupar-te pels detalls. i deixa de sentir-se com a màgia i comença a fer un sentit predictible. smart coordinator go build go run de Un pla de construcció go.mod Títol: Mod Abans que Go toqui mai els vostres arxius fonts, necessita saber què construir i en quin ordre. i Aquests arxius defineixen el , que és l'arbre de dependència complet del vostre projecte, juntament amb versions precises per a cada mòdul. Mitjançant la lectura d'aquests arxius, la cadena d'eines de Go sap exactament quins paquets formen part de la vostra construcció i quin codi extern recollir, verificar i incorporar. go.mod go.sum module graph Un cop carregat el gràfic del mòdul, Go avalua cada paquet per determinar el seu conjunt de fonts. Això inclou cada arxiu .go que pertany al paquet, filtrat per etiquetes de construcció, sistema operatiu, arquitectura i qualsevol restricció que hagis especificat. Només després d'aquesta avaluació el compilador sap quin codi realment necessita processar. Això assegura que les teves construccions són deterministes: el mateix El comandament executat en diferents màquines produeix resultats idèntics, assumint les mateixes versions de mòduls. go build Un aspecte clau de la modernitat és el paper de la Directiva en Aquesta directiva declara la versió mínima de Go per a la qual està dissenyat el mòdul. Això influeix en diverses característiques de la construcció: la semàntica del llenguatge, el comportament del compilador i fins i tot l'anàlisi estàtica. La directiva, la semàntica del llenguatge, el comportament del compilador i les comprovacions poden diferir: la cadena d'eines les imposa durant la compilació. Això forma part de l'enfocament de Go en la reproductibilitat, assegurant que el codi es comporti de manera coherent a través d'entorns. go go.mod go A finals d’aquest període, l’edifici té una : sap quins paquets compilar, en quina seqüència, i quins arxius pertanyen a cada paquet. Amb aquesta informació a la mà, passa al següent pas: compilar paquets i enllaçar-los en binaris, segur que no es perdrà ni es malcompilarà res. complete, ordered build plan Combinació i vinculació en la pràctica Una vegada que Go té el pla de construcció del sistema mòdul, comença a convertir el codi en una cosa que la màquina pot executar. Això passa en dues etapes diferents: compilació i vinculació.Comprendre aquestes etapes és clau per apreciar per què les construccions de Go són ràpides, deterministes i escalables. La compilació és per paquet Anem a compilar Cada paquet - ja sigui part del vostre projecte o una dependència externa - es tracta com una unitat independent. Això vol dir que si un paquet no ha canviat des de l'última construcció, Go pot saltar la recompilació completament, fins i tot si altres paquets que depenen d'ell estan sent reconstruïts. one package at a time intermediate artifacts El paral·lelisme és un altre avantatge d'aquest enfocament per paquet: ja que el compilador coneix el gràfic de dependència, pot compilar múltiples paquets independents simultàniament, aprofitant plenament les CPU multi-core. El vincle és selectiu és el procés de combinar paquets compilats en un sol executable. Els paquets de la biblioteca mai es vinculen per si sols, existeixen purament com a artefactes reutilitzables per a altres paquets. Aquesta distinció és important: quan s'executa En un projecte, Go pot compilar desenes de paquets però produir zero binaris si cap dels paquets és principal! Enllaç only links main packages into binaries go build ./... La vinculació és sovint l'etapa més costosa en una construcció perquè implica combinar totes les dependències en un sol executable, resoldre símbols i incrustar metadades. El que acaba en el binari El binari final és més que només el codi compilat. Inclou: Tots els paquets dependents que són accessibles des del principal Construcció de metadades, inclosa la versió del mòdul i la informació de compromís Instruccions a nivell de màquina optimitzades per a la plataforma objectiu Aquesta combinació és la raó per la qual els binaris de Go són autònoms i reproduïbles: inclouen tot el necessari per executar-se sense dependre de biblioteques externes o entorns de temps d'execució. Des d'una perspectiva humana, això fa que la implementació sigui senzilla. Des d'una perspectiva de màquina, el sistema de construcció pot verificar i guardar-ho tot de manera eficient, assegurant que les construccions repetides són ràpides i deterministes. El caixer construït: el centre de la gravetat Al cor de la velocitat i predictibilitat de Go és la seva Cada paquet compilat, cada artefacte intermedi i fins i tot algunes sortides d'eines s'emmagatzemen en una memòria cau adreçada al contingut, que permet a Go reutilitzar el treball a través de construccions, comandes i fins i tot Comprendre com funciona la memòria cau és essencial per entendre per què les construccions de Go se senten gairebé instantànies, fins i tot per a grans projectes. build cache go run Què és el Cache Store La memòria cau de la construcció és més que simplement binaris compilats. Artifactes de paquets compilats (arxius .a) per a tots els paquets del gràfic de construcció Resultats de les proves, inclosa la informació de l'èxit emmagatzemada Sortides d'eines temporals necessàries per a l'execució de la prova de marxa o marxa La memòria cau viu en el disc (per defecte en ) i és completament determinista, el que significa que el mateix paquet compilat amb les mateixes entrades sempre produirà la mateixa entrada de memòria cau. Això assegura que les construccions repetides, o les construccions entre màquines diferents, produeixin resultats idèntics. $GOCACHE Adreçat al contingut, no basat en el timestamp A diferència dels sistemes de construcció tradicionals que depenen de timestamps d'arxiu, Go utilitza Cada clau de cache és una funció de: content-based hashing El contingut del codi font Versió compiladora Totes les banderes construïdes La plataforma de destinació (GOOS/GOARCH) Variables ambientals pertinents Aquest disseny garanteix que les edicions són reproduïbles i evita errors de memòria cau falsos a causa de canvis inofensius com ara timestamps o ordre d'arxius. Invalidesa de cache explicada Fins i tot amb una memòria cau robusta, a vegades Go recompila paquets. causes comuns inclouen: Modificar el codi font o les etiquetes de construcció Canviar les banderes del compilador o les variables ambientals Renom de fitxers dins d'un paquet El sistema de memòria cau de Go és intel·ligent: només reconstrueix el que realment necessita la reconstrucció. Fins i tot els petits canvis no semàntics poden desencadenar la recompilació si afecten el hash de construcció del paquet, però en cas contrari, la memòria cau es confia implícitament. Per què el cache és segur de confiar El build cache està dissenyat per ser transparent i fiable: Rarament s'ha de netejar manualment La reconstrucció des de zero produeix artefactes idèntics anar a córrer, anar a provar, i anar a construir tot l'aportació de forma coherent És per això que les construccions incrementals de Go són tan ràpides: el compilador mai fa més treball del necessari. Des d'una perspectiva de desenvolupador, se sent màgic. Des d'una perspectiva de sistemes, és simplement una canonada optimitzada que tracta els artefactes de paquets com a ciutadans de primera classe. Producció d’artefactes go build Anem a construir La comanda go build és el cavall de treball de la cadena d'eines Go. La seva tasca és simple de descriure però sofisticada en l'execució: Comprendre el que De fet, ajuda a predir el seu comportament i evitar sorpreses comunes. compile packages, link them if necessary, and produce a binary that is correct and reproducible go build Com es construeixen els paquets Quan correu en un mòdul o paquet, l'eina examina primer el gràfic de dependència derivat de la Cada paquet del gràfic es controla contra la memòria cau de la construcció: si la memòria cau conté un artefacte compilat vàlid per a un paquet, Go el reutilitza en comptes de recopilar. go build go.mod Perquè va , tocar un sol arxiu dins d'un paquet pot desencadenar una reconstrucció de tot el paquet. Inversament, si una dependència no ha canviat, mai no es reconstrueix, fins i tot si altres paquets depenen d'ella. És molt bo, fins i tot per a grans projectes. operates at the package level incremental builds El vincle i el binari final Com hem dit abans, només produeix un executable per als paquets principals. Els paquets de la biblioteca es compilen en artefactes intermedis, però mai es vinculen per si mateixos. Quan es vincula un paquet principal, Go combina tots els paquets compilats en un sol binari. Aquest procés també incorpora metadades a l'executable, incloent: go build Informació de versió del mòdul Compromís hash (si està disponible) Metadades de construcció específiques de la plataforma Per defecte, la inclusió de detalls de control de versió es regeix per la bandera, que està configurada per defecte com a "auto" i marca la informació VCS quan el context del repositori ho permet (utilitzar Omet o Més detalls es poden trobar a la documentació . -buildvcs -buildvcs=false -buildvcs=true Aquí Això fa que els binaris de Go siguin autònoms i altament reproduïbles, permetent-vos desplegar-los amb confiança sense preocupar-vos de perdre dependències. On van els artefactes (disculpeu 😀) per defecte, escriure el binari en el directori actual, anomenat després del paquet. Si el paquet és una biblioteca, no produeix un binari en absolut, només assegura que el paquet i les seves dependències es compilen. Bandera o utilització Construir múltiples paquets en un sol pas. go build go build -o ./... En Windows, els executables tenen una Quan es construeixen múltiples paquets principals alhora (per exemple, ) sense , Go escriu un binari per paquet principal al directori actual. .exe ./cmd/... -o Edificis previsibles i fiables La combinació de la compilació per paquet, la memòria cau i l'enllaç selectiu assegura que la construcció és previsible. Les construccions són reproduïbles a través de màquines El codi inalterat mai no es reconstrueix innecessàriament Els artefactes intermedis es reutilitzen per optimitzar el temps de construcció En breu, No és només la compilació de codi, és . go build orchestrating a deterministic pipeline that balances human convenience with machine efficiency Confort sense privilegis especials go run Anem a córrer Si és el cavall de treball que produeix artefactes que es poden desplegar, Molts desenvolupadors pensen en això com "compilant i executant en un pas", però no és: sota el capó, aprofita el mateix sistema de construcció com , només està optimitzat per a la comoditat en lloc de la persistència de l'artefacte. go build go run go build Què De fet, fa go run Quan el tipus (o una llista de fitxers), Go avalua primer el paquet i les seves dependències de la mateixa manera que Tots els paquets compilats en memòria cau es reutilitzen, de manera que el compilador fa un treball mínim per mantenir el codi inalterat. . go run main.go go build links the main package into a temporary binary, executes it, and deletes the binary once the program finishes Des d’un punt de vista clandestí, Això explica per què les invocacions repetides del mateix programa sovint se senten instantànies: el pesat aixecament ja s'ha fet, i només l'enllaç o el canvi de paquets poden desencadenar la compilació. go run Per què Sentiment diferent go run Tot i que comparteixen el mateix canal subjacent, pot sentir-se més lent en certs escenaris. Com que produeix un binari temporal cada vegada, l'enllaç es repeteix, fins i tot si totes les dependències estan en memòria cau. Per als programes petits, aquest sobrecàrrec és negligible, però per als projectes amb grans gràfics de dependència, pot ser notable. go run Una altra diferència és que Aquest és exactament el punt: el comerç reutilitza binari per a la facilitat d'execució. No cal pensar on col·locar el binari o com anomenar-lo, l'eina ho gestiona automàticament. go run does not leave a persistent artifact Quan És l'eina correcta - i quan no és go run És ideal per: go run Experiments ràpids o guions Executar programes d'una sola vegada sense molestar el sistema de fitxers Prova de petits programes de manera interactiva És menys adequat per: Producció o desplegament servidors de llarga durada on l'enllaç repetit afegeix sobrecàrrega Pipelines CI on la memòria cau de binaris persistents és més eficient En aquests casos, el patró recomanat és , que li dóna els beneficis de la memòria cau, la reproductibilitat i un artefacte persistent sense sacrificar el rendiment. go build && ./binary La correcció oculta Anar a provar Anar a provar El El projecte es basa en els mateixos principis que i Comprendre com interactuen les proves amb el sistema de construcció ajuda a explicar per què algunes proves s'executen instantàniament mentre que altres desencadenen una reconstrucció, i per què l'enfocament de Go és ràpid i predictible. go test go build go run Reutilització de la compilació en proves Quan correu , Go primer determina el gràfic de dependència del paquet de prova, inclosos els paquets importats. Igual que amb o Això vol dir que les grans suites de proves sovint poden començar a executar-se gairebé immediatament, ja que la major part del treball de compilació ja s'ha fet. go test reused from the build cache go build go run Fins i tot quan hi ha múltiples paquets involucrats, Go només reconstrueix els paquets que realment han canviat.La combinació de la compilació per paquet i la memòria cau assegura que les proves incrementals són ràpides, fins i tot en projectes grans. Resultats de la prova Caching A més de l'emmagatzematge de paquets compilats, també Si una prova passa i cap de les seves dependències o banderes rellevants han canviat, Go pot saltar la reexecució de la prova completament. caches test results L'emmagatzematge de resultats de la prova només s'aplica en el mode de llista de paquets (per exemple, o ) En el mode de directori local ( sense args de paquet), el caching està desactivat. go test . go test ./... go test Aquest comportament està controlat per la La bandera, per exemple, L'execució de les forces independentment dels resultats cachats. ( Repetició de les proves/benchmarks. és la manera idiomàtica d'abandonar els resultats en memòria cau. veure Per a més detalls) -count go test -count=1 -count -count=1 Documentació L'emmagatzematge de resultats de les proves millora la productivitat dels desenvolupadors i l'eficiència de la CI, especialment per a grans projectes amb una àmplia cobertura de proves. . the system should avoid unnecessary work while preserving correctness Invalidesa cache en proves Una prova es pot tornar a executar automàticament si: El codi de prova mateix ha canviat. Qualsevol dependència de la prova ha canviat. Les banderes que afecten la prova han canviat. Les banderes no cacheables o els arxius / env modificats també invaliden la reutilització. En cas contrari, Go confia en el resultat emmagatzemat, sabent que és Aquest enfocament redueix les construccions "flaky" causades per reconstruccions innecessàries i enfatitza la predictibilitat sobre la conveniència cega. deterministic and reproducible Instal·lació Handy Snippets Aquí teniu alguns útils Invocacions que aprofiten el comportament de caching: go test Fresh run: go test -count=1 ./... - com hem vist anteriorment, això desactiva la memòria cau dels resultats del test. Stressar una prova: anar a la prova -run '^TestFoo$' -count=100 ./pkg - executa TestFoo 100 vegades per comprovar la flakiness. Estabilitat del banc: prova -bench. -compte=3 - executa tots els indicadors de referència 3 vegades per obtenir mesuraments estables. Per què és important per als desenvolupadors Des de la perspectiva d'un desenvolupador, la combinació de la memòria cau de la construcció i la memòria cau dels resultats de la prova crea un flux de treball que se sent instantani i fiable: Els petits canvis només desencadenen els passos de compilació necessaris. Passar les proves rarament tornen a córrer, tret que alguna cosa canviï. Els desenvolupadors poden iterar ràpidament sense preocupar-se per l'estat ocult. Tractant tant els paquets com els resultats de les proves com a artefactes cacheables de primera classe, Go fa que els assajos siguin ràpids i predictibles, reforçant la mateixa optimització "humà + màquina" que subjaça. i . go build go run Observació i Debugging del sistema construït La majoria del temps, el sistema de construcció de Go fa exactament el que s'espera, tranquil·lament i eficientment. Quan alguna cosa s'atura, però, la cadena d'eines li dóna una visibilitat directa i de baix nivell sobre el que està fent. Fent parlar la Toolchain Go proporciona un petit conjunt de banderes que exposen la canonada de construcció sense canviar el seu comportament: -x imprimeix els comandes reals executats durant la construcció. Això inclou invocacions de compiladors, passos de enllaç i execucions d'eines. És la manera més ràpida de respondre a la pregunta: "Què està fent realment Go ara mateix?" -n mostra el que s'executaria, sense executar els comandaments. Això és útil quan voleu comprendre el pla de construcció sense desencadenar una reconstrucció. Això li permet inspeccionar els arxius intermedis, el codi generat i els artefactes temporals produïts durant la compilació o l'enllaç. Aquestes banderes converteixen la cadena d'eines Go d'una caixa negra en una canonada transparent. Importantment, no deshabiliten la memòria cau, simplement fan visibles els hits de memòria cau i les mancances. Comprendre per què es va reconstruir un paquet Una de les fonts més comunes de confusió és una reconstrucció de paquets "sense raó aparent". Un paquet es reconstrueix quan qualsevol entrada a la seva clau de memòria cau canvia. Les entrades inclouen codi font, etiquetes de construcció, banderes de compiladors, plataforma de destinació i variables ambientals rellevants. Els canvis de dependència es propaguen cap amunt a través del gràfic de paquets. utilitzant , sovint es pot veure si Go va reutilitzar un artefacte emmagatzemat o va recopilar un paquet, i inferir per què del context. Com a primera resposta. -x go clean -cache Forçar la reconstrucció (quan realment ho voleu dir) De vegades realment voleu eludir la memòria cau. Per exemple, quan valideu una construcció neta o debuggeu problemes de la cadena d'eines. Una reconstrucció forçosa de paquets, ignorant els artefactes compilats emmagatzemats go clean -cache neteja tot el cache de construcció Aquestes opcions són intencionadament explícites i lleugerament incòmodes. Go està dissenyat per fer que la reutilització sigui correcta per defecte, i la invalidació manual de la memòria cau sigui l'excepció. Si us trobeu netejant la memòria cau regularment, sovint és un senyal que alguna cosa més en la configuració de la construcció necessita atenció. Evitar les supersticions Perquè el sistema de construcció de Go és determinista, adonar rarament ajuda. , , i Dóna proves concretes del que està succeint, que gairebé sempre és suficient per explicar el comportament sorprenent. -x -n -work Si confia en això: Els edificis estan adreçats, Els paquets són la unitat de treball. i la cache és segura per reutilitzar, El comportament de debugging de la construcció es converteix en una qüestió d'observació en lloc d'assaig i error. Implicacions per a projectes reals Les opcions de disseny darrere del sistema de construcció de Go no són accidentals. Es mostren més clarament una vegada que es va més enllà dels petits exemples i comença a treballar en bases de codi reals: pipelines d'integració contínua, grans repositoris i fluxos de treball guiats per l'editor. sentir-se ràpid localment és el que fa que Go escali tan bé en entorns de producció. go build Pipelines i reproductibilitat L'enfocament de Go en les construccions deterministes i adreçades al contingut fa que sigui particularment adequat per a CI. Atès que les sortides de construcció es deriven íntegrament del contingut font, les versions de mòduls i la configuració explícita, les construccions de CI es comporten de manera coherent a través de màquines i entorns. Aquesta predictibilitat també fa que les construccions de Go siguin molt amigables amb la memòria cau. Ja sigui que utilitzeu una memòria cau de construcció compartida, capes de contenidors o infraestructura de memòria cau remota, el model de compilació a nivell de paquet de Go s'ajusta de forma natural. Monorèpos i grans bases de codis En els grans repositoris, la memòria cau de construcció es converteix en un límit de rendiment. Com que les memòries cachés de Go compilen paquets de forma independent, els paquets petits i ben definits es poden reutilitzar en moltes construccions amb un mínim sobrecapte. El flip-side és que els paquets massa grans o estretament enllaçats poden convertir-se en barreres. Un petit canvi en un paquet molt utilitzat pot invalidar una gran part de la memòria cau, augmentant els temps de construcció a tot el repositori. Editors, Tooling i Automatització El mateix model de construcció dóna suport a l'ecosistema d'eines de Go. Els editors de codi, els servidors d'idiomes, els linterns i els generadors de codi es basen en la mateixa comprensió del codi a nivell de paquet. Atès que la cadena d'eines exposa un tub de construcció clar i determinista, les eines poden integrar-se profundament sense endevinar o reimplementar la lògica de la construcció. Aquesta és una de les raons per les quals la utilització d'eines Go se sent inusualment coherent: els editors i els sistemes CI veuen el codi de la mateixa manera que el compilador fa. Des de l'autocompletat fins a la refactorització fins a les proves automatitzades, tot es basa en els mateixos supòsits sobre els paquets, les dependències i la memòria cau. Conclusió: Confiar en el model El sistema de construcció de Go té èxit perquè fa un compromís clar: optimitza per a la predictibilitat sobre l'intel·ligència, i per a l'estructura explícita sobre el comportament implícit. A la superfície, això sembla simplicitat. A sota, és una canonada acuradament dissenyada que tracta els paquets com la unitat de treball, el contingut com la font de la veritat, i la memòria cau com una característica de correcció en lloc d'un hack de rendiment. Un cop internalitzat aquest model, molts comportaments quotidians comencen a tenir sentit.Les construccions són ràpides no perquè el Go faci menys treball, sinó perquè evita fer-ho. El treball. és convenient perquè reutilitza la mateixa maquinària com L'execució de les proves és fiable perquè els resultats de les proves es cachegen utilitzant les mateixes regles deterministes que els paquets compilats. innecessària go run go build Per als humans, això significa menys sorpreses, fluxos de retroalimentació més ràpids i eines que es comporten de manera coherent a través d'editors de codi, màquines i sistemes CI. Per a les màquines, significa construccions reproduïbles, artefactes amigables amb la memòria cau i un sistema que s'escala de forma natural a mesura que creixen les bases de codi. Si hi ha una presa, és aquesta: el sistema de construcció de Go no és una cosa per lluitar o treballar al voltant. És una API en el seu propi dret - una que recompensa la comprensió. Un cop confieu en el model, la cadena d'eines deixa de sentir-se màgica i comença a sentir-se fiable, que és exactament el que voleu de la infraestructura que construeix el vostre codi.