Kitabı oku: «Programación en Go», sayfa 2

Yazı tipi:

Capítulo 1
INSTALACIÓN Y USO DE GO
1.1 INSTALANDO GO

Go está disponible para descarga gratuita desde su página web:

http://golang.org

En la página principal, haga clic en el enlace titulado “Download Go”, que le llevará a la página de descargas (Figura 1.1), donde encontrará los diversos paquetes para su sistema operativo (Windows, Linux, Mac).

Tan solo instale el paquete descargado y siga las instrucciones de instalación. Si la instalación ha tenido éxito, puede abrir una sesión de línea de comandos y verificar que el ejecutable go está en su ruta de programas:

$ go version go version go1.15 darwin/amd64

La instalación por defecto de Go consiste en:

• El compilador go, que le permite generar sus archivos ejecutables.

• Herramientas útiles para la programación: depuradores, analizadores de rendimiento, comprobadores de código...

• La biblioteca estándar de Go: una extensa colección de funcionalidades que usted puede incorporar en sus programas.

• La documentación estándar de Go, accesible a través del comando godoc.


Figura 1.1 Página web oficial de descargas de Go.

1.2 COMANDOS BÁSICOS DE GO

A continuación, se muestran algunos de los comandos más habituales de Go, que pueden serle de utilidad durante su proceso de aprendizaje:

• go build

– Ejecutándose desde el directorio raíz de su proyecto Go, genera un archivo ejecutable del proyecto.

• go run <archivo>.go

– Para ejecutar su programa de Go directamente, sin generar un ejecutable. Útil durante la etapa de desarrollo.

• go fmt ./...

– Ejecutándose desde el directorio raíz de su proyecto, reformatea todos los archivos de código fuente según el formato estándar de Go. Su uso es, si no obligado de facto, sí muy recomendable.

• go vet ./...

– Ejecutándose desde el directorio raíz de su proyecto, busca patrones de código susceptibles de ocasionar errores o comportamientos incorrectos.

• godoc

– Abre un servidor web en la dirección http://localhost:6060/. Si lo abre desde su navegador, podrá navegar localmente por toda la documentación de las diferentes bibliotecas estándar de Go, disponibles en la instalación por defecto.

• go get

– Permite descargar bibliotecas y utilidades de línea de comandos suministradas por terceros.

• go mod

– Permite gestionar sus proyectos locales, así como sus dependencias hacia bibliotecas de terceros.

1.3 EDITANDO SU CÓDIGO EN GO

Para programar en Go, tan solo necesita un editor de texto plano, como un bloc de notas. Sin embargo, es aconsejable utilizar un editor de código o un entorno integrado de desarrollo, que proporciona funcionalidades tales como resaltado de código, comprobación in situ de errores, depuración visual, etc.

Go es compatible con la gran mayoría de editores de código y entornos de desarrollo, directamente o a través de extensiones. La tabla de la Figura 1.2 enumera, por orden alfabético, algunos de los entornos más populares para el desarrollo de proyectos en Go. Aunque su editor favorito no esté en la tabla, es posible que ofrezca soporte básico o resaltado de sintaxis para Go.


Figura 1.2 Algunos editores y entornos de desarrollo populares para Go.

1.4 COMPILANDO Y EJECUTANDO SU PRIMER PROGRAMA

Comenzaremos a familiarizarnos con Go y sus herramientas mediante la creación y compilación de un programa básico. No se preocupe si no entiende todo su contenido, ya que será explicado en profundidad en los próximos capítulos.

Para empezar, abra un editor de texto plano y cree un archivo cuya extensión sea .go. Por ejemplo, hola.go. Copie el siguiente contenido:


Del código anterior, quizás haya podido deducir algunos de los siguientes componentes de un programa básico en Go:

• El punto de entrada del programa se marca mediante func main() {. El programa comenzará ejecutando el código contenido en el bloque delimitado por llaves { y }.

• Cada fichero está encabezado por una directiva package, que otorga un nombre común para la agrupación (paquete) de todos los archivos Go en un directorio. El punto de entrada del programa debe estar encabezado por package main (paquete principal).

• Cuando se incorporan funcionalidades de la biblioteca estándar o de otras bibliotecas de terceros (por ejemplo, para mostrar un mensaje en pantalla), deben incorporarse explícitamente los paquetes que las contienen mediante la directiva import. En el programa de ejemplo, la directiva import "fmt” permite usar funcionalidades de escritura de mensajes en pantalla (entre otras).

• Cualquier texto escrito después de dos barras // es ignorado por el compilador hasta el final de la línea. Allí puede dejar algunos comentarios que ayuden a documentar o entender el código.

– Puede usar comentarios de múltiples líneas si los sitúa entre los símbolos /* y */.

• El comando fmt.Println muestra un mensaje en pantalla. Está compuesto por el nombre del paquete en el que está guardado (fmt) y el nombre de la función Println. Entre paréntesis, se escribe el texto a mostrar (que debe ir entre comillas dobles).

Para saber más sobre Println y sobre el paquete fmt, puede probar a ejecutar el comando godoc en su línea de comandos. Se ejecutará un servidor web local en el que puede abrir la siguiente dirección en su navegador:

http://localhost:6060/pkg/fmt

Dicha dirección le llevará a la documentación del paquete fmt, donde podrá encontrar información completa sobre las funciones que proporciona, muchas de las cuales se explicarán en el próximo capítulo y en el capítulo 14.

Para ejecutar el programa, vaya desde la línea de comandos al directorio que contiene el archivo hola.go y ejecute el siguiente comando:

$ go run hola.go

A continuación del comando escrito, verá el siguiente mensaje:

¡Hola, geómidos!

Esto permite ejecutar el programa en su ordenador personal (ya que tiene instalada la herramienta Go). Para generar un archivo ejecutable que pueda ser ejecutado en otro ordenador, debe utilizar el comando go.build:

$ go build hola.go

El comando anterior creará un archivo ejecutable apto para la misma arquitectura y el mismo sistema operativo desde el cual compila. Si quisiera generar ejecutables para otros sistemas operativos y arquitecturas de procesador, puede usar las variables de entorno GOOS y GOARCH, respectivamente:

GOOS=windows GOARCH=386 go build hola.go GOOS=linux GOARCH=arm64 go build hola.go

Los comandos anteriores generarían ejecutables para Windows con procesadores Intel de 32 bits, y para Linux con procesadores ARM de 64 bits, respectivamente.

Capítulo 2
SINTAXIS BÁSICA DE GO

Este capítulo explica las características básicas del lenguaje de programación Go. Los fundamentos del lenguaje Go no son, en concepto, muy diferentes de los de otros lenguajes de programación, como Java o C.

2.1 TIPOS DE DATOS BÁSICOS

Una variable es un espacio reservado en la memoria del ordenador para guardar datos cuyo valor puede cambiar durante la vida del programa: un número, una letra, un texto, un luchador de Street Fighter... Una variable irá asociada a un nombre para poder referirnos a ella durante el programa: matrícula, total, jugador1...

Go es un lenguaje con “tipado estático”, lo que significa que cada variable tiene un tipo de dato asociado y solo podrá guardar valores de su tipo de dato.

Go provee los siguientes tipos de datos básicos, a partir de los cuales es posible definir variables y ejecutar operaciones básicas:

• bool es el tipo booleano. Los posibles valores que puede tomar son dos: true (cierto) o false (falso).

• string permite guardar cadenas de texto, y acepta cualquier carácter Unicode mediante la codificación UTF-8 (es decir, todos los caracteres del alfabeto latino, más caracteres de otras culturas, incluso emojis).

• int es un número entero con signo (es decir, permite guardar tanto números enteros positivos como negativos). Su tamaño depende de la plataforma para la cual se compila el programa. Esto significa que el compilador escogerá el tamaño de las variables int que mejor se adapten a la arquitectura del procesador para el cual se compila (generalmente, concordará con el número de bits del procesador: 32 o 64).

– Cuando sea necesario concretar con exactitud el tamaño de una variable, se pueden usar los siguientes tipos: int8, int16, int32, int64 para números enteros con signo de 8, 16, 32 y 64 bits, respectivamente.

• uint es un número entero sin signo (es decir, no acepta números negativos). Al igual que int, su tamaño dependerá de la plataforma (32 o 64 bits).

– Cuando se requiera concretar con exactitud el tamaño de una variable, se pueden usar los siguientes tipos: uint8, uinti6, uint32 o uint64.

• byte es el equivalente de uint8.

• rune es un equivalente para int32 y se usa para representar un carácter (letras, números, signos de puntuación, emojis, y un largo etcétera).

• float32 y float64 representan números de coma flotante (también llamados “números reales”) de 32 y 64 bits, respectivamente.

• complex64 y complex128 son números complejos cuyas partes real e imaginaria están representadas por números reales de 32 y 64 bits, respectivamente.

– Un literal de número complejo se escribe como en el siguiente ejemplo: 2.23 + 3i.

2.2 CADENAS DE TEXTO. EL TIPO string

Go permite definir cadenas de texto explícitamente, insertando un texto cualquiera entre comillas dobles:

texto := "- Hola, ¿cómo estás?"

Si una cadena ha de contener un texto mostrado en diversas líneas, puede introducir el carácter especial de nueva línea \n allá donde quiera que termine una línea y empiece otra:

texto := "- Hola, ¿cómo estás?\n- Estoy bien, gracias."

Si una cadena ha de contener comillas dobles en su interior, estas deben especificarse como un carácter especial \", para que Go no las confunda como el final de una cadena de texto:

texto := "Podría decirse que estoy \"bien\"..."

Cuando un texto contiene múltiples líneas o comillas dobles, puede resultar más limpio substituir el delimitador de comillas dobles por el de “acento grave”; esto le permitirá escribir cadenas en múltiples líneas, tomando los saltos de línea como literales. El equivalente a la cadena anterior, sería:

texto := `- Hola, ¿cómo estás? - Estoy "bien", gracias.`

No debe confundir los delimitadores de cadenas con la comilla simple ', que sirve para especificar caracteres individuales, del tipo byte o rune.

2.3 DEFINICIÓN DE VARIABLES

La manera de definir una variable, dado un nombre y un tipo de dato, es:

var <nombre> <tipo> [ = <valor> ]

Por ejemplo:

var dias int var meses int = 12

Las líneas anteriores definirían una variable llamada dias, del tipo int, y otra variable llamada meses, del tipo int, a la que se le asigna un valor inicial de 12.

Si no se provee un valor inicial, las variables serán inicializadas automáticamente con el “valor cero” de cada tipo de dato: 0 para tipos numéricos, false para bool, y la cadena vacía "" para string.

En aras de la brevedad, se puede omitir tanto la palabra var como su tipo si se usa el operador de inicialización :=:

meses := 12

El compilador de Go inferirá el tipo de la variable meses a un int (ya que es un número sin parte decimal), y aunque el valor de la variable cambie, el tipo siempre deberá ser int.

El símbolo := solo se puede usar para definir una variable. Una vez definida, se usará el operador de asignación = si se desea cambiar su valor. Por ejemplo:

paso := 1 // definición de la variable con un valor inicial paso = 2 // cambio del valor de la variable

Las guías de estilo de Go recomiendan declarar variables con el operador : = siempre que se pueda, aunque las variables globales y las que no tengan valor inicial deberán declararse mediante la forma precedida por var.

2.4 CONVERSIONES EXPLÍCITAS DE TIPOS

En Go, al contrario de lo que ocurre en otros lenguajes de tipado estático, si se quiere asignar una variable numérica a otra variable de otro tipo numérico, se deberá explicitar el tipo de destino de la siguiente manera:

var segundos int8 = 30 var horas int horas = int(segundos)

En el fragmento anterior, se indica a Go que el valor de la variable segundos, del tipo int8, se va a copiar en otra variable del tipo int. Aunque es obvio que cualquier valor del tipo int8 (8 bits) cabe en una variable del tipo int (32 o 64 bits), Go obliga a hacer explícita esta conversión.

Si la conversión se hace desde un tipo entero de tamaño superior al tipo de destino, se usan los bits menos significativos del tipo de origen que caben en el tipo de destino.

Si la conversión se hace desde un tipo de coma flotante, se trunca la parte con decimales y se asigna la parte entera. Por ejemplo:

distancia := 12.78 kms := int(distancia)

En el ejemplo anterior, la variable kms tomará el valor 12 (eliminando, sin redondeo alguno, el 0.78 de la variable original).

2.5 CONSTANTES

Una constante es un valor literal al que se le asigna un nombre, que no puede cambiar durante la vida del programa. Su definición es similar a la de una variable, pero reemplazando la palabra var por la palabra const. Por ejemplo:

const Pi = 3.1416

o

const Pi float64 = 3.1416

Cuando se definen múltiples constantes, se pueden agrupar semánticamente bajo la misma directiva const. Por ejemplo:


2.6 BASES DE NUMERACIÓN

Además de la comúnmente usada base decimal (en la que cada dígito puede tomar diez valores distintos, del 0 al 9), Go permite usar otros tipos de bases de numeración según el prefijo que añadamos a cada número (Figura 2.1).


Figura 2.1 Bases de numeración en Go.

Cuando queramos agrupar bloques de dígitos, podemos insertar un guión bajo “_” entre estos. Go no lo tendrá en cuenta a la hora de establecer el valor.

Ejemplos:

productoInteriorBruto := 1_419_000_000_000 bitsAgrupados := 0b_1000_1001_0110

2.7 OPERADORES NUMÉRICOS

Go permite hacer las siguientes operaciones con tipos de datos númericos, por orden de precedencia:

1. Agrupaciones de operaciones, delimitadas por paréntesis.

2. Multiplicaciones, divisiones (operadores * y /), así como el resto de la división entera (o módulo, operador %).

3. Sumas y restas (operadores + y -).

El orden de precedencia hace referencia a qué operaciones se evalúan primero, cuando una expresión compleja engloba múltiples operaciones. Primero, se evalúan las operaciones de mayor precedencia. En caso de múltiples operaciones con la misma precedencia, estas se evalúan según su posición en la expresión, de izquierda a derecha.

Por ejemplo, dada la siguiente expresión:

a := 8 + 3 * (1 + 2) % 5

1. Primero evaluaría la expresión entre paréntesis, ya que es la de mayor precedencia: a := 8 + 3 * 3 % 5

2. Luego evaluaría la multiplicación y el módulo. Al ser de la misma precedencia, primero evaluaría la multiplicación, ya que está más a la izquierda: a := 8 + 9 % 5

3. Y continuaría por el resto de la división entera: a := 8 + 9

4. Siendo la suma la operación de menos precedencia, sería la última en evaluarse: a := 12

Además de los anteriores operadores matemáticos, Go provee los operadores de incremento (++) y decremento (--), que van detrás de una variable que se quiere incrementar o decrementar, respectivamente:

a := 10 b := 20 a++ b--

Después de ejecutar el anterior programa, la variable a contendría el valor 11 y la variable b contendría el valor 19.

A diferencia de otros lenguajes de programación con los que el lector pueda estar familiarizado, los operadores de incremento y decremento no pueden ir dentro de otras expresiones.

2.8 OPERADORES NUMÉRICOS DE COMPARACIÓN

Go permite comparar expresiones numéricas (Figura 2.2). El resultado de una comparación será un bool (true o false). Cuando se mezclan con las operaciones numéricas del apartado anterior, las operaciones de comparación son las de menor precedencia.


Figura 2.2 Operadores de comparación.

2.9 OPERADORES APLICABLES AL TIPO string

El operador + aplicado entre string, retorna un nuevo string con las cadenas concatenadas:

a := "el cocherito" b := "leré" concat := a + “ " + b

En el ejemplo anterior, la variable concat contendría la cadena "el cocherito leré".

Los operadores de comparación también pueden usarse para comparar cadenas de texto.


INFORMACIÓN: Go hará distinción entre mayúsculas y minúsculas, por lo que "HOLA" == "hola" retornará false y "ZZZ" < "aaa" también retornará false, ya que el valor numérico de la Z mayúscula es menor al de la a minúscula.

2.10 OPERADORES LÓGICOS CON bool

Cualquier variable o expresión que retorne un bool puede combinarse con otros booleanos mediante los siguientes operadores lógicos (Figura 2.3), resultando en otros valores booleanos. Cuando se mezclan con las operaciones de comparación del apartado anterior, las operaciones de lógica son las de menor precedencia.


Figura 2.3 Operadores lógicos.

2.11 OPERADORES LÓGICOS A NIVEL DE BIT

Las variables numéricas también pueden verse como agrupaciones de dígitos binarios (bits) con los que podemos realizar las siguientes operaciones, que se aplican tras comparar los bits de igual posición en dos operandos (Figura 2.4).


Figura 2.4 Operadores lógicos a nivel de bit.

2.12 SALIDA ESTÁNDAR DE DATOS

El paquete fmt, del cual pudo ver una pequeña muestra en el capítulo anterior, permite mostrar datos en su terminal de línea de comandos (también llamado salida estándar) mediante las siguientes funciones:

fmt.Print fmt.Println fmt.Printf

fmt.Print y fmt.Println enviarán a la salida estándar los datos que sitúe entre paréntesis, y separados por comas, a continuación del nombre de la función. Para los datos que no sean cadenas de texto, Go hará una conversión genérica a texto antes de enviarlos a la salida estándar. Go, además, añadirá un espacio entre los diferentes datos dentro de una misma invocación a fmt.Print o fmt.Println.

Ejemplo:

x := 33 fmt.Println("Hola, número", x, "!")

Salida estándar:

Hola, número 33 !

La diferencia entre fmt.Print y fmt.Println es que fmt.Println añade un salto de línea al final. Es decir, sucesivas invocaciones a fmt.Print serían mostradas una detrás de otra, en la misma línea; mientras que sucesivas invocaciones a fmt.Println serían mostradas en diferentes líneas, una debajo de otra.

Cuando requiera un control más exhaustivo de cómo se deben mostrar los datos, la función fmt.Printf admite una cadena de texto en la que puede colocar unas “marcas de formato”, conocidas como verbos. A continuación, separados por comas, se colocan los datos que Go debe introducir en el lugar de cada uno de los verbos.

Por ejemplo, el siguiente ejemplo intercala los verbos %v, que muestran el valor de una variable, y que serán substituidos por las variables a continuación del texto de formato, en orden de aparición:

cosa := "depósito" x := 36 y := 84 fmt.Printf("Coordenadas de %v: (%v, %v)\n", cosa, x, y)

Salida estándar:

Coordenadas de depósito: (36, 84)

Observe que fmt.Printf no añade ninguna nueva línea al final, por lo que si necesita que el siguiente texto aparezca en la línea siguiente, debe finalizar la cadena de formato con el carácter especial de nueva línea: '\n'.

La tabla de la Figura 2.5 muestra algunos otros verbos útiles aceptados por fmt.Printf. Para más detalles, visite la documentación del paquete fmt a través del comando godoc que se introdujo en el capítulo anterior.


Figura 2.5 Algunos verbos útiles para fmt.Printf.