¿QUÉ
ES GO?
¿Has escuchado hablar de Go, este nuevo lenguaje de programación cuya
mascota es un adorable Gopher? No, pues no te preocupes, en esta ocasión me
gustaría contarte sobre Go y el por qué deberías darle una oportunidad de estar
en tu stack de tecnológico, te adelanto, vale mucho la pena. Bien, una vez
dicho esto, no perdamos más el tiempo y comencemos. 🐿
¿GO O GOLANG?
Go es un lenguaje de programación concurrente y compilado, desarrollado por
los ingenieros de Google. Go vio la luz en el año 2009, esto hace a Go un
lenguaje relativamente nuevo, pero que esto no nos engañe, Go es un lenguaje
maduro, con el cual se han desarrollado miles de proyectos alrededor del mundo,
inclusive, versiones actuales de Go están escritas con el mismo Go.
Podemos hacer uso de Go si nos encontramos trabajando en Windows, MacOS y
en ciertos sistemas GNU/Linux. Go es un lenguaje de tipado
estático, una vez declaremos el tipo de dato de nuestra variable, la variable
no podrá cambiar de tipo en todo el programa, eso sí, en Go no es necesario
definir el tipo, como lo podemos observar en la línea número cuatro, con las
variables x y y. Tipificación dinámica, duck Typing.
Si hay algo en lo que Go sin duda destaca es en el tema de
concurrencia. Sí, en otros lenguajes de programación también es posible
trabajar con hilos, pero en Go sucede algo peculiar. En Go no existen los
Threads perse, en lugar de ellos existen las goroutine, que son algo así como
Threads ligeros. Con los goroutine y los canales podemos crear cientos de miles
de "hilos" sin ningún problema. Esto hace a Go una excelente opción
si lo que deseamos es optimizar la mayor cantidad de recursos posibles. Existen
decenas de casos en los cuales empresas han dejado de utilizar x tecnología
para comenzar a usar Go. Uno de los casos que más me agrada es el de Iron.io, en su arítulo nos cuentan como
pasarón de tener 30 servidores con Ruby on Rails a tener unicamente 2 con Go
(Concurrencia).
Go está pensado para ser implementado en tareas las cuales no
tengan mucha interacción con los usuarios, es más un lenguaje de sistemas que
de aplicaciones. Un área muy recurrente en donde podemos implementar Go es del
lado del servidor, ya sea que nuestro programa funcione como backend, como un
microservicio o se encuentre realizando tareas un poco más complejas, tal vez,
procesando datos.
Algo que me parece muy interesante, e importante a mencionar, es
que Go admite la programación orientada a objetos, pero no de la forma
tradicional que conocernos. Si bien podemos crear objetos (estructuras),
definir atributos y métodos, con Go no podremos hacer uso de la herencia y el
polimorfismo quedará delegado al uso de interfaces. Si vienes de un lenguaje
orientado a objetos, como Java, es probable que te lleves un par de sorpresas.
Veamos un ejemplo de programación orientada a objetos con Go. Otra de las
principales características de Go es que
este no cuenta con excepciones, puesto en palabras de los desarrolladores: esto añade una complejidad innecesaria
al lenguaje y al entonor de ejecución. Así que mucho cuidado al programar en
Go, hay que validar mucho si no queremos que nuestro programa se caiga.
GO LENGUAJE DE PROGRAMACIÓN
¡El día de la publicación del lenguaje Go, Francis
McCabe, desarrollador del lenguaje de programación Go! (anteriormente llamado Go),
solicitó que se le cambiase el nombre al lenguaje de Google para
evitar confusiones con su lenguaje. McCabe creó Go! en el año 2003; sin
embargo, aún no ha registrado el nombre. Go es un nuevo lenguaje de
programación para sistemas lanzado por Google en noviembre de 2009. Aunque
empezó a ser desarrollado en septiembre de 2007 por Robert Griesemer, Rob Pike
y Ken Thompson.
CARACTERÍSTICAS
·
·
Go usa una sintaxis similar a C.
·
Go usa tipado estático (statically typed)
y su rendimiento es comparable al de lenguajes como C y C++ ya que, al igual
que estos, el compilador convierte el código de Go a código máquina.
·
Go tiene muchas de las características y facilidad de lenguajes dinámicos
como Python.
·
Aun siendo un lenguaje diseñado para la programación de sistemas, provee de
un recolector de basura, reflexión y otras
capacidades de alto nivel que lo convierten en un lenguaje muy potente.
·
El binario de Go tiene la característica de compilación cruzada de manera nativa.
·
Go admite el paradigma de programación orientada a objetos, pero a
diferencia de los lenguajes de programación más populares no dispone de
herencia de tipos y tampoco de palabras clave que denoten claramente que
soporta este paradigma. Otro detalle que puede resultar confuso es que la
definición de un tipo ("clase") se realiza por medio de declaraciones
separadas (interfaces, structs, embedded values). Go permite el uso de
delegación (a través de embedded values) y polimorfismo (por medio de
interfaces).
·
Go utiliza la concurrencia a través de las gorutinas.
·
Go es un lenguaje de programación pensado en aprovechar sistemas con
múltiples procesadores.
Es un lenguaje concurrente que soporta canales de
comunicación basados en el lenguaje CSP de Sir Charles Antony Richard Hoare,
creador del algoritmo de ordenación QuickSort y
ganador del Turing en 1980. La concurrencia en Go es
diferente a los criterios de programación basados en bloqueos como pthreads.
Los lenguajes más utilizados como C++, Java o C# son
más pesados y voluminosos. La sencillez es la característica principal de Go,
su sintaxis es clara y concisa. Mientras que C es tristemente célebre por la
complejidad de la sintaxis de sus declaraciones, Go utiliza inferencia
implícita de tipos pudiéndose de esta manera evitar la declaración explícita de
variables. La declaración de variables es simple y conveniente, y difiere de la
de C en el uso del operador de auto asignación := que interfiere los tipos en base al valor asignado.
Go admite la tipificación dinámica de datos también
conocida como duck Typing presente en multitud de lenguajes dinámicos como por
ejemplo JavaScript, Ruby o Python. Un struct puede implementar una
interfaz de forma automática,6
lo cual es una característica potente y novedosa.
No son ni hilos, ni co-rutinas ni procesos. La
comunicación entre gorutinas se realiza a través de una característica del
lenguaje llamada canales —basada en CSP—, que es más segura y fácil de usar que
los sistemas predominantes basados en bloqueos de pthreads o características
modernas de Java.
EXCEPCIONES
Go no utiliza excepciones. Los creadores del lenguaje
han dado varios motivos para que esto sea así. La principal es que añadir una
capa de excepciones agrega una complejidad innecesaria al lenguaje y al entorno
de ejecución. Por definición las excepciones deberían ser excepcionales, pero
al final se acaban usando como controladores del flujo de la aplicación y dejan
de tener la finalidad de excepcionalidad. Según los creadores, las excepciones
tienen que ser realmente excepcionales y el uso que se le da mayoritariamente
no justifica su existencia.
INNOVACIÓN
Durante muchos años, los desarrolladores han tenido
que elegir entre lenguajes de programación de tipado estático compilados, por
regla general, bastante complejos pero que proveen grandes características
relacionadas con la optimización y el rendimiento y lenguajes de tipado
dinámico interpretados con características de mucho más alto nivel que hacían
su aprendizaje, uso y sintaxis más sencilla y por tanto divertido programar en
ellos, eso si, sacrificando rendimiento y control.
Go mezcla lo mejor de ambos mundos y nos aporta una
sintaxis sencilla, fácil de interpretar y divertida junto a la potencia que nos
ofrece un lenguaje fuertemente tipado y compilado incorporando además
características de alto nivel que facilitan el uso del lenguaje por los
desarrolladores.
DIFERENCIAS PRINCIPALES CON C
Aunque su sintaxis es similar, Go difiere mucho de C.
Véanse algunos ejemplos.
DECLARACIONES AL REVÉS
En Go las declaraciones se realizan al revés desde la
perspectiva de C (o C++ o Java). La idea principal en C es que se declara una
variable como una expresión que denota su tipo. Según los creadores, aunque la
idea detrás de la declaración de tipos en C es buena, los tipos y las
expresiones gramaticales no se mezclan demasiado bien y el resultado puede ser
confuso. Go sin embargo, separa la expresión y la sintaxis de tipo, lo cual
simplifica las cosas.
PUNTO Y COMA
En Go el uso del carácter punto y coma “;“ al final de
una instrucción es opcional.
ARITMÉTICA DE PUNTEROS
Go no tiene aritmética de punteros. Según los
creadores, la razón es la seguridad. Sin aritmética de punteros es posible
crear un lenguaje en el que no se puede obtener una dirección ilegal que sea
usada de forma incorrecta. La falta de aritmética de punteros simplifica la
implementación del recolector de basura. Además, optimizando el compilador y
con el hardware actual, un bucle que utiliza los índices de un array puede ser
tan eficaz como un bucle que utiliza aritmética de punteros.
++ y --
En Go, el uso de ++ y -- para incrementar y
decrementar el valor de una variable es una sentencia y no una expresión.
Además, solo puede utilizarse en su versión sufija pues según los autores, la
versión prefija pierde todo su sentido en la ausencia de aritmética de
punteros.
PROGRAMACIÓN ORIENTADA A OBJETOS
Para algunos autores, la herencia o las clases no son
conceptos esenciales para el paradigma de POO, sino más
bien un medio de implementación. Existen desde hace tiempo lenguajes orientados
a objetos que no admiten clases, sino que se basan en prototipos, como Javascript o Self. Según
declaraciones de Alan Kay, creador de Smalltalk,
lo esencial del paradigma es el paso
de mensajes.7
Go tiene tipos y métodos, y permite un estilo de programación orientado a objetos que
reemplaza el uso de clases por estructuras las cuales admiten construir
jerarquías, es decir, no soporta
el uso herencia y favorece en su
lugar el patrón de composición. En Go,
el concepto de “interfaz“ es similar al usado en Java: cualquier objeto
(value) que cumpla el contrato especificado por una interfaz (sin
necesidad de una declaración explícita) obtiene ese tipo. También existen
formas de embeber estructuras dentro de otras estructuras para obtener algo
análogo a las subclases. Los métodos de Go son más
generales que los de C++ o Java, y se
incluyen en las estructuras declarando funciones asociadas a estas. Pueden ser
definidos para cualquier tipo de datos; no solo para los registros. Por su parte
las interfaces de Go a diferencia de lenguajes como Java, son de tipo
implícito, es decir que se considera que la interfaz ha sido implementada
cuando una estructura implementa sus métodos aun cuando esto no se especifique.
SINTAXIS, TIPOS DE DATOS Y PALABRAS RESERVADAS
¡Buenas! Continuamos los capítulos de programación en
Go. Recordemos que en el capítulo anterior revisábamos algunos aspectos básicos
del lenguaje, así como también aprendimos a instalar el compilador en nuestros
equipos. En este capítulo continuaremos con algunos aspectos de carácter
general de la sintaxis de Go antes de saltar a los temas de estructura de
bloques.
ESTRUCTURA DE UN ARCHIVO. GO
Retomando el código de ejemplo del capítulo anterior con el cual verificamos la correcta
instalación de Go desde símbolos de sistema o terminal, en dicho ejemplo
podemos identificar las siguientes secciones en el código:
1 – Declaración de paquetes.
2 – Paquetes importados.
3 – Funciones.
4 – Variables.
5 – Declaraciones y expresiones.
6 – Comentarios (no abordados en dicho ejemplo).
Antes de continuar es necesario conocer la sintaxis de los comentarios en
Go la cual es:
/*
este es un comentario */
Todo comentario es ignorado por el compilador independientemente de su
contenido. Solamente es de ayuda para el programador.
Los espacios en blanco son un caso similar a los comentarios. Tal y como en
C y C++ puedes poner espacios en blanco u otros caracteres similares (tabulares
por ejemplo) en cualquier parte del código sólo tomando unas pequeñas
consideraciones (no puede haber caracteres en blanco en el nombre de un
identificador, etc.), en Go también se pueden tomar la mayoría de esas
libertades. La libertad más importante de la que se carece en Go es la posibilidad
de separar la llave de apertura de una sentencia por medio de un carácter de
nueva línea, es decir:
1. package
main
2. import "fmt"
3.
4. func main()
5. { /*
unexpected semicolon or newline before { */
6. fmt.Println("Hello,
World!")
7. }
Ahora continuemos con el tema principal, la estructura de los programas.
Recordando el ejemplo del capítulo anterior, ahora se ha añadido un comentario
previo que identifica cada parte del programa:
1. /*Paquete
al que corresponde este archivo.
2. Todo
archivo de Go debe localizarse en un paquete*/
3. package
main
4.
5. /*Línea de
preprocesador. Incluye el paquete fmt
6. que tiene
definidas las funciones y métodos de
7. entrada y
salida */
8. import "fmt"
9.
10. /*Función
principal con la que se comienza a
11. ejecutar
el programa */
12. func main(){
13. /*Del
paquete fmt importa el método Println el
14. cual
muestra el texto en pantalla */
15. fmt.Println("¡Has
instalado Go correctamente!")
16. }
Cabe señalar que no existe algún carácter especial que se deba añadir para
terminar una línea de código más que el carácter de fin de línea. Internamente
el compilador agrega el punto y coma «;» al final de cada sentencia.
1. fmt.Println("Ésta
es una línea de código")
2. fmt.Println("Ésta
también")
3. fmt.Println("Ésta
es la tercer línea de código")
IDENTIFICADORES Y PALABRAS RESERVADAS
Al igual que en muchos otros lenguajes de programación, en Go puedes
declarar variables, funciones y elementos con un identificador único que tú
desees. Un identificador inicia con una letra de la «A»-«Z» (mayúscula o
minúscula) o bien con un guión bajo («_») seguido de una combinación de 0 o N
letras, guiones y dígitos decimales.
identificador
= [a-zA-Z_]+[a-zA-Z0-9_]*
Se debe de tener cuidado que los identificadores nunca sean iguales a las
palabras reservadas. La siguiente es la lista de palabras reservadas de Go:
break |
default |
funct |
interface |
select |
case |
defer |
go |
map |
struct |
chan |
else |
goto |
package |
switch |
const |
fallthrough |
if |
range |
type |
continue |
for |
import |
return |
var |
TIPOS DE DATOS
Como se mencionaba desde el capítulo anterior, Go es un lenguaje de
programación con tipado estático y por tanto es necesario declarar las
variables antes de usarlas. La razón por la que esto es necesario es porque el
compilador necesita conocer cuánto espacio en memoria necesita reservar para
variables y cómo interpretar la información guardada en ese espacio de memoria.
Booleanas |
Variables lógicas
con valor true o false. |
Numéricas |
Representan números
enteros o de punto flotante. |
Cadenas |
Secuencia de bytes
que representan cadenas de texto inmutable, no es posible cambiar el
contenido de una cadena. |
Derivadas |
Punteros, arreglos,
estructuras, uniones, funciones, slices, interfaces, Maps, Channels. |
Las variables en Go se clasifican como:
RANGOS DE VALORES DE ENTEROS Y FLOTANTES
Los números enteros que maneja Go son independientes de la arquitectura del
procesador, es decir, no cambian los rangos de valores entre arquitecturas de
procesadores como ocurre con C. Los tipos de enteros son:
Tipo |
Descripción |
Rango |
uint8 |
Unsigned |
8-bits
(0 a 255) |
uint16 |
Unsigned |
16-bits
(0 a 65535) |
uint32 |
Unsigned |
32-bits
(0 a 4294967295) |
uint64 |
Unsigned |
64-bits
(0 a 18446744073709551615) |
int8 |
Signed |
8-bits
(-128 a 127) |
int16 |
Signed |
16-bits
(-32768 a 32767) |
int32 |
Signed |
32-bits
(-2147483648 a 2147483647) |
int64 |
Signed |
64-bits
(-9223372036854775808 a 9223372036854775807) |
Por su parte los tipos numéricos con punto flotante son:
Tipo |
Descripción |
float32 |
IEEE-754
32-bit floating-point numbers |
float64 |
IEEE-754
64-bit floating-point numbers |
complex64 |
Números
complejos con float32 partes reales e imaginarias |
complex128 |
Números
complejos con float64 partes reales e imaginarias |
Además de números decimales enteros y de punto flotante, Go cuenta con
otras implementaciones con sus tamaños específicos:
Tipo |
Descripción |
byte |
8-bits
(0 a 255) |
rune |
32-bits
(-2147483648 a 2147483647) |
uint |
32 o 64
bits |
int |
32 o 64
bits |
uintptr |
Entero
guarda los bits no interpretados de un puntero |
EJEMPLO
El clásico programa Hola mundo en Go es similar a como se
haría en C++. Con este típico ejemplo podemos apreciar que en cuanto a sintaxis
son muy similares:
package main
import "fmt"
func main() {
fmt.Println("Hola,
mundo.")
}
La notación de los comentarios es exactamente la misma
que la de C++
/* ...
...
... */
// ...
Hola, me parece super interesante tu blog :)
ResponderEliminarQue interesante el Go de programación no sabía que existía ese lengua de programación muy buena.
ResponderEliminarexcelente contenido
ResponderEliminarBuen trabajo
ResponderEliminar