1. Code
  2. Coding Fundamentals

Programemos con Go: Organización del Código del Lenguaje Go

Go es un lenguaje especial entre los lenguajes modernos. Es muy tajante. Por ejemplo, hay un formato cierto. Go te dirá cómo espaciar tu código y dónde colocar tus llaves. Pero va mucho más profundo que eso.
Scroll to top

Spanish (Español) translation by Javier Salesi (you can also view the original English article)

Go es un lenguaje especial entre los lenguajes modernos. Es muy tajante. Por ejemplo, hay un formato cierto. Go te dirá cómo espaciar tu código y dónde colocar tus llaves. Pero va mucho más profundo que eso.

Go también te dirá cómo capitalizar tus funciones y variables para hacerlas públicas o privadas. Dictaminará la estructura del directorio de tu código. Ésto podría llegar como una sorpresa para los desarrolladores que vienen a Go desde lenguajes de programación más liberales.

En éste artículo, exploraré algunas de las restricciones de Go, discutiré sus méritos, y sugeriré opciones para situaciones comunes.

Proyecto Euler

Cuándo comencé a aprender Go, elaboré una solución al Problema #6 y sólo la puse en un subdirectorio junto con soluciones para otros problemas en otros lenguajes. Ver Proyecto Euler.

El problema es que Go no quiere que sólo coloques aleatoriamente los archivos Go por cualquier parte. Más tarde me dí cuenta que mientras si funciona en casos muy simples dónde no importas otros paquetes, en realidad no es adecuado.

Dependencias

Cada programa no trivial se compone de múltiples archivos o módulos o componentes o clases. Sólo usaré "archivo" como un término general. Con frecuencia están agrupados en librerías, paquetes o ensamblados. Sólo utilizaré "paquete" como un término general. El código que escribes depende del código en otros archivos y paquetes.

Necesitas decirle a tu código cómo encontrar esos paquetes y archivos para usar su funcionalidad. Cada lenguaje tiene su propio término: import (importar), include (incluir), require (requerir). Sólo usaré "importar" como término general.

Algunos lenguajes (o herramientas específicas del lenguaje) también te permiten instalar dependencias desde un repositorio de paquete remoto e instalarlas en una ubicación local estándar desde la que puedes importar.

En los lenguajes de programación más comunes, tienes mucha libertad. En C/C++, le dices al compilador/enlazador dónde están los archivos y las librerías estáticas (usando modificadores de la línea de comando o variables de entorno como INCLUDE_DIR). En Python, puedes instalar paquetes de PyPI usando setup.py o con pip de PyPI y repositorios de control remotos. Después importas basándote en la ruta de búsqueda del paquete sys.path.

A la Manera de Go

Go, como siempre, es más prescriptivo. Puede ofender tu creatividad que no puedas decidir dónde colocar las cosas, pero al final del día no importa realmente, y hay suficiente flexibilidad para atender varias situaciones.

Go requiere que coloques tu código en un espacio de trabajo. Un espacio de trabajo es sólo un directorio con tres subdirectorios: src, pkg y bin. Se recomienda que mantengas todos tus proyectos bajo un solo espacio de trabajo. De ésta forma pueden depender mutuamente y compartir paquetes de terceros.

Nota: Actualmente trabajo en Windows y uso PowerShell para muchos de los ejemplos interactivos. Para la siguiente sección, quería mostrar la estructura de directorios de mi espacio de trabajo usando el comando tree. Windows tiene su propio comando tree.exe, pero es muy limitado (no tiene niveles). Supuestamente hay un comando tree muy completo para Windows aquí.

Pero el sitio fue inalcanzable. Terminé disparando un contenedor de Docker ejecutando Ubuntu, montando mi espacio de trabajo Go como /docs/Go, y usando el comando tree de Linux para mostrarlo. Así que no te confundas si ves un entorno Linux mostrando directorios y archivos de Windows con extensiones .exe.

Aquí está mi actual espacio de trabajo en Go. El directorio bin contiene varios comandos/herramientas de Go, y el depurador delve. El directorio pkg tiene un subdirectorio con la plataforma (Win 64) que contiene los paquetes organizados por su origen (github.com, golang.com, etc.). El directorio src tiene subdirectorios similares para el repositorio o sitio web de origen (github.com, golan.org, etc.).

1
root@67bd4824f9d5:/docs/Go# tree -n -L 3
2
3
|-- bin
4
|   |-- dlv.exe
5
|   |-- go-outline.exe
6
|   |-- go-symbols.exe
7
|   |-- gocode.exe
8
|   |-- godef.exe
9
|   |-- golint.exe
10
|   |-- gometalinter.exe
11
|   |-- gopkgs.exe
12
|   |-- gorename.exe
13
|   |-- goreturns.exe
14
|   `-- guru.exe
15
|-- pkg
16
|   `-- windows_amd64
17
|       |-- github.com
18
|       |-- golang.org
19
|       |-- gopkg.in
20
|       `-- sourcegraph.com
21
`-- src
22
    |-- github.com
23
    |   |-- alecthomas
24
    |   |-- derekparker
25
    |   |-- go-web-crawler
26
    |   |-- golang
27
    |   |-- google
28
    |   |-- lukehoban
29
    |   |-- multi-git
30
    |   |-- newhook
31
    |   |-- nsf
32
    |   |-- rogpeppe
33
    |   |-- tpng
34
    |   `-- x
35
    |-- golang.org
36
    |   `-- x
37
    |-- gopkg.in
38
    |   `-- alecthomas
39
    `-- sourcegraph.com
40
        `-- sqs
41
42
43
27 directories, 11 files
44

Veamos lo que hay dentro de los proyectos origen que he creado bajo src : the go-web-crawler. Es muy simple aquí: sólo una lista llana de archivos Go, una licencia, y un archivo README.

1
root@67bd4824f9d5:/docs/Go# tree src/github.com/go-web-crawler/ -n
2
src/github.com/go-web-crawler/
3
|-- LICENSE
4
|-- README.md
5
|-- channel_crawl.go
6
|-- main.go
7
`-- sync_map_crawl.go
8
9
0 directories, 5 files

GOROOT y GOPATH

Dos variables de entorno controlan tu destino en la tierra de Go. GOROOT es dónde está la instalación de Go:

1
09:21:26 C:\Users\the_g\Documents\Go> ls Env:\GOROOT

2


3
Name                           Value

4
----                           -----

5
GOROOT                         C:\Go\

6


7
09:21:35 C:\Users\the_g\Documents\Go> ls c:\go

8


9


10
    Directory: C:\go

11


12


13
Mode                LastWriteTime         Length Name

14
----                -------------         ------ ----

15
d-----        8/16/2016  10:38 AM                api

16
d-----        8/16/2016  10:38 AM                bin

17
d-----        8/16/2016  10:38 AM                blog

18
d-----        8/16/2016  10:38 AM                doc

19
d-----        8/16/2016  10:38 AM                lib

20
d-----        8/16/2016  10:38 AM                misc

21
d-----        8/16/2016  10:38 AM                pkg

22
d-----        8/16/2016  10:38 AM                src

23
d-----        8/16/2016  10:38 AM                test

24
-a----        8/16/2016   1:48 PM          29041 AUTHORS

25
-a----        8/16/2016   1:48 PM           1168 CONTRIBUT

26
-a----        8/16/2016   1:48 PM          40192 CONTRIBUT

27
-a----        8/16/2016   1:48 PM           1150 favicon.i

28
-a----        8/16/2016   1:48 PM           1479 LICENSE

29
-a----        8/16/2016   1:48 PM           1303 PATENTS

30
-a----        8/16/2016   1:48 PM           1638 README.md

31
-a----        8/16/2016   1:48 PM             26 robots.tx

32
-a----        8/16/2016   1:48 PM              5 VERSION

Nota que el directorio raíz de Go parece un superconjunto de un espacio de trabajo con los directorios src, bin y pkg.

GOPATH apunta a tu espacio de trabajo. Así es como Go encuentra tu código.

1
09:21:53 C:\Users\the_g\Documents\Go> ls Env:\GOPATH
2
3
Name                           Value
4
----                           -----
5
GOPATH                         c:\Users\the_g\Documents\Go

Hay un montón de otras variables de entorno relacionadas con Go, muchas de las cuáles requeriste establecer en el pasado (por ejemplo, GOOS y GOARH ). Ahora son opcionales, y no deberías meterte con ellas a menos que realmente lo necesites (por ejemplo, cuándo se hace una compilación múltiple). Para ver todas las variables de entorno de Go, escribe: go env .

1
09:51:10 C:\Users\the_g> go env
2
set GOARCH=amd64
3
set GOBIN=
4
set GOEXE=.exe
5
set GOHOSTARCH=amd64
6
set GOHOSTOS=windows
7
set GOOS=windows
8
set GOPATH=c:\Users\the_g\Documents\Go
9
set GORACE=
10
set GOROOT=C:\Go
11
set GOTOOLDIR=C:\Go\pkg\tool\windows_amd64
12
set CC=gcc
13
set GOGCCFLAGS=-m64 -mthreads -fmessage-length=0
14
set CXX=g++
15
set CGO_ENABLED=1

Instalar e importar

Cuándo creas un programa o librería en Go, puedes instalarla. Los programas van al directorio bin de tu espacio de trabajo, y las librerías van al directorio pkg del espacio de trabajo. En Windows, descubrí que tu %GOPATH%/bin no está en el directorio %PATH%, así que Windows no pudo encontrar mi ejecutable. Lo agregué al PATH de Windows y todo funcionó. Aquí está cómo revisar en PowerShell que tu PATH contenga el directorio bin en tu espacio de trabajo:

1
10:56:19 C:\Users\the_g> $env:path.split(";") | grep go

2


3
C:\Go\bin

4
c:\Users\the_g\Documents\Go\bin

Veamos todo ello en acción.

Si voy a mi directorio go-web-crawler y escribo go install entonces go-web-crawler.exe es creado en c:\Users\the_g\Documents\Go\bin :

1
11:09:18 C:\Users\the_g> ls $env:GOPATH/bin

2


3


4
    Directory: C:\Users\the_g\Documents\Go\bin

5


6


7
Mode                LastWriteTime         Length Name

8
----                -------------         ------ ----

9
-a----        8/15/2016  11:05 AM       15891456 dlv.exe

10
-a----        8/15/2016  10:08 AM        3972608 go-outline.exe

11
-a----        8/15/2016  10:10 AM        4502528 go-symbols.exe

12
-a----        9/18/2016  10:14 AM        1849856 go-web-crawler.exe

13
-a----        8/15/2016  10:08 AM       12097024 gocode.exe

14
-a----        8/15/2016  10:17 AM        6642688 godef.exe

15
-a----        8/15/2016   9:32 AM        6625792 golint.exe

16
-a----        8/15/2016  10:14 AM        6352896 gometalinter.exe

17
-a----        8/15/2016  10:10 AM        2738688 gopkgs.exe

18
-a----        8/15/2016  10:10 AM        6961152 gorename.exe

19
-a----        8/15/2016  10:09 AM        7291904 goreturns.exe

20
-a----        8/15/2016  10:11 AM        9722368 guru.exe

Ahora puedo ejecutarlo desde mi web crawler de Go desde cualquier lugar.

1
11:10:32 C:\Users\the_g> go-web-crawler.exe
2
3
found: http://golang.org/ "The Go Programming Language"
4
found: http://golang.org/cmd/ ""
5
not found: http://golang.org/cmd/
6
found: http://golang.org/pkg/ "Packages"
7
found: http://golang.org/pkg/os/ "Package os"
8
found: http://golang.org/pkg/fmt/ "Package fmt"
9
found: http://golang.org/ "The Go Programming Language"

Múltiples Entornos en Go

Eso está muy bien, pero a veces la vida no es tan sencilla. Puedes querer tener múltiples espacios de trabajo separados. Es más, puedes querer tener múltiples instalaciones de Go (por ejemplo, diferentes versiones) y múltiples espacios de trabajo para cada una. Puedes hacer ésto al establecer dinámicamente GOPATH para cambiar el espacio de trabajo y establecer GOROOT para cambiar la instalación activa de Go.

Hay varios proyectos de código abierto para gestión de paquetes, dependencias y entornos virtuales. Por alguna razón, la mayoría no soportan Windows. No estoy seguro por qué tales herramientas tienen que ser para una plataforma específica. Puedo escribir un gestor de entorno Go multiplataforma por mí mismo uno de éstos días.

Conclusión

Go se trata de eliminar la complejidad incidental. A veces viene como muy estricto y prescriptivo. Pero si te pones a pensar como los diseñadores que utilizan Go, empiezas a comprender que el evitar, prohibir u obligar a ciertas cosas realmente hace todo más sencillo.