Documentos de Académico
Documentos de Profesional
Documentos de Cultura
Logro
Al finalizar esta charla los participantes podrán usar los playground
disponibles en la web para escribir pequeños programas con el
lenguaje de programación GO de google. Además podrán conocer la
forma en que se crea un programa ejecutable GO con un editor de
notas y se ejecuta en una pantalla cmd.
Utilidad
1. Conocer los playGround GO
2. Escribir programas GO
3. Comprender la sintaxis del lenguaje
4. Utilizar el paquete fmt
5. Crear interfaces.
Qué es GO
Go es un lenguaje de programación concurrente y compilado
inspirado en la sintaxis de C, que intenta ser dinámico como Python y
con el rendimiento de C o C++. Ha sido desarrollado por Google (2009)
Actualmente está disponible en formato binario para los sistemas
operativos Windows, GNU/Linux, FreeBSD y Mac OS X, pudiendo
también ser instalado en estos y en otros sistemas mediante el código
fuente.
Go es un lenguaje de programación compilado, concurrente,
imperativo, estructurado, orientado a objetos y con recolector de
basura que de momento es soportado en diferentes tipos de sistemas
UNIX, incluidos Linux, FreeBSD, Mac OS X y Plan 9 (puesto que parte
del compilador está basado en un trabajo previo sobre el sistema
operativo Inferno). Las arquitecturas soportadas son i386, amd64 y
ARM.
¿Por qué debería de aprender Go?
1 – Pocas palabras reservadas que facilitan el aprendizaje.
2 – Incorpora su propio recolector de basura.
3 – Sintaxis minimalista y simple. Con Go, menos es más.
4 – Fácil implementación de concurrencia vía Gorutinas.
5 – Estructurado principalmente en funciones.
6 – Sintaxis similar a C y C++.
7 – Strings y Maps incorporados al lenguaje.
8 – Rápido de compilar.
Aspectos previos a comenzar
Hay que tener en cuenta algunos aspectos que han sido descartados de Go (cada
uno descartado por alguna razón en específico) antes de comenzar:
1 – Herencia.
2 – Sobrecarga.
3 – Dependencias circulares entre paquetes.
4 – Aritmética de apuntadores.
5 – Aserciones.
Librería fmt
Función básica
Detalles
Todos los programas en Go inician por la función main en el paquete main.
Además no es necesario terminar las sentencias con ; (punto y coma).
En el programa anterior, podemos ver que la primera sección del programa
compuesta por la primera línea contiene la declaración del package actual,
que en nuestro caso es main. La segunda sección del programa compuesta
por la tercera línea contiene la declaración de las rutas de importación que
utiliza la palabra reservada import. Las rutas de importación cargan
básicamente librerías (clases) propias del core o de terceros. La tercera
parte del programa compuesta por las tres últimas líneas define la función
main la cual es el punto de inicio del programa. Para agregar más de una
ruta de importación se puede agregar las líneas que sean necesarias.
Formas de invocar librerías
import "fmt"
import "math/rand"
import (
"fmt"
"math/rand"
)
Documentación Go :
https://golang.org/doc/
Paquetes go: https://golang.org/pkg/
Especificaciones del lenguaje:
https://golang.org/ref/spec
KeyWords
Tipos de Datos
Podemos concebir una variable como una etiqueta con nombre, que
se vincula a un valor.
Supongamos que tenemos un número entero, 103204948, y
queremos almacenar esta larga cifra en una variable en lugar de
volver a escribirla una y otra vez. Para hacerlo, podemos usar un
nombre fácil recordar, como la variable i. Para almacenar un valor en
una variable, usaremos la siguiente sintaxis:
i := 1032049348
s := “Hola a todos!"
f := 45.06
b := 5 > 9 // Un valor lógico es devuelto (boolean)
array := [4]string{"item_1", "item_2", "item_3", "item_4"}
slice := []string{“uno", “dos", “tres"}
m := map[string]string{“letra": "g", “numero": “siete", “símbolo":
"&"}
Declarar variables
En Go, hay varias formas de declarar una variable y, en algunos casos, más
de una forma de declarar exactamente la variable y el valor idénticos.
Podemos declarar una variable llamada i del tipo de datos int sin iniciarla.
Esto significa que declararemos un espacio para ubicar un valor, pero no le
daremos un valor inicial:
var i int
Esto crea una variable del tipo de datos int declarada como i.
Podemos inicializar el valor usando el operador igual (=), como en el
siguiente ejemplo:
var i int = 1
En Go, las dos formas de instrucción se denominan declaraciones variables
largas; también podemos usar una declaración variable corta:
i := 1
En este caso, contamos con una variable llamada i y un tipo de datos int.
Cuando no especifiquemos un tipo de datos, Go lo inferirá.
En Go, debido a que todos los valores tienen un valor zero, no puede
haber valores undefined como en otros lenguajes. Por ejemplo, un
boolean en algunos lenguajes podría ser undefined, true o false, lo
que permite tres estados para la variable. En Go, no podemos exceder
el valor de estados two para un valor boolean.
Verbos Generales
%v // the value in a default format
// when printing structs, the plus flag (%+v) adds field names
%#v // a Go-syntax representation of the value
%T // a Go-syntax representation of the type of the value
%% // a literal percent sign; consumes no value
Ejemplo:
a:=40.00
fmt.Printf("Su edad es %v años, variable 'a' es de tipo %T", a,a)
Verbo booleano
%t // the word true or false
a:=40
b:=50
fmt.Printf("%v>%v=%t",a,b,a>b)
Verbos entero
• %b // base 2
• %c // the character represented by the corresponding Unicode code
point
• %d // base 10
• %o // base 8
• %q // a single-quoted character literal safely escaped with Go syntax.
• %x // base 16, with lower-case letters for a-f
• %X // base 16, with upper-case letters for A-F
• %U // Unicode format: U+1234; same as "U+%04X"
Ejemplos
a:=1100
fmt.Printf("%v en base 2 es %b\n",a,a)
fmt.Printf("%v en base 8 es %o\n",a,a)
fmt.Printf("%v en base 16 min es %x\n",a,a)
fmt.Printf("%v en base 16 may es %X\n",a,a)
Verbos de coma flotante y complejos
• %b // decimalless scientific notation with exponent a power of two,
• // in the manner of strconv.FormatFloat with the 'b' format,
• // e.g. -123456p-78
• %e // scientific notation, e.g. -1.234456e+78
• %E // scientific notation, e.g. -1.234456E+78
• %f // decimal point but no exponent, e.g. 123.456
• %F // synonym for %f
• %g // %e for large exponents, %f otherwise
• %G // %E for large exponents, %F otherwise
Cadena y segmento de bytes (tratados de
manera equivalente con estos verbos):
%s // the uninterpreted bytes of the string or slice
%q // a double-quoted string safely escaped with Go syntax
%x // base 16, lower-case, two characters per byte
%X // base 16, upper-case, two characters per byte
a:="Víctor"
fmt.Printf("Victor = %s ; Victor = %q ",a,a)
Ejemplos
text1 := fmt.Sprintf("Hello %s", "World")
text2 := fmt.Sprintf("%d + %d = %d", 2, 3, 5)
text3 := fmt.Sprintf("%s, %s (Age: %d)", "Obama", "Barack", 55)
fmt.Println(text1)
fmt.Println(text2)
fmt.Println(text3)
Nombrar variables: reglas y estilos
La asignación de nombres a variables es bastante flexible, pero hay
reglas que se deben tener en cuenta:
package main
import "fmt"
func main() {
nombres := []string{"María", "Juan", "Roberto", "Ana"}
for i, n := range nombres {
fmt.Printf("Índice: %d = %q\n", i, n)
}
}
Utilizamos la variable nombres
en un ámbito más amplio, por lo
que sería normal darle un
nombre más significativo para
ayudar a recordar lo que
representa en el programa. Sin
embargo, usamos las variables i
y n inmediatamente en la
siguiente línea de código, y
luego no las volvemos a usar.
Debido a esto, no confundirá a
alguien que lea el código
respecto de dónde se usan las
variables o qué significan.
A continuación, veremos algunas notas sobre el estilo de las variables.
El estilo consiste en usar MixedCaps o mixedCaps en lugar de guiones
bajos para nombres de varias palabras.
Lo más importante respecto del estilo es preservar la uniformidad y
que el equipo del que forma parte esté de acuerdo acerca de este.
Estilo convencional Estilo no convencional Por qué no convencional
Los guiones bajos no son
userName user_name
convencionales.
Priorizar i sobre index, ya
i Índice que es más corto.
Si intentamos usar una instrucción variable corta más de una vez para el mismo
nombre de variable, también observaremos un error de compilación. Esto puede
ocurrir por equivocación, por lo cual entender el mensaje de error es útil:
i := 5
i := 10
Output
no new variables on left side of :=
Variables globales y locales
Al usar variables dentro de un programa, es importante tener en cuenta el
ámbito de variable. El ámbito de una variable se refiere a espacios concretos
desde los cuales es posible acceder a ella dentro del código de un programa
determinado. Esto es decir que no es posible el acceso a todas las variables
desde todas las partes de un programa determinado; algunas variables serán
globales y algunas locales.
Las variables globales existen fuera de las funciones. Las locales existen
dentro de las funciones.
import "fmt"
var g = "global"
func printLocal() {
l := "local"
fmt.Println(l)
}
func main() {
printLocal()
fmt.Println(g)
}
Aquí usamos var g = "global“ para crear una variable global fuera de
la función. Luego definimos la función printLocal(). Dentro de la
función, se asigna una variable local llamada “l” que luego se
imprime. El programa se cierra llamando a printLocal() e imprimiendo
la variable global “g”.
import "fmt"
var g = "global"
func printLocal() {
l := "local"
fmt.Println(l)
fmt.Println(g)
}
func main() {
printLocal()
fmt.Println(g)
}
Comenzamos declarando una variable global g, var g = "global". En la
función main, llamaremos a la función printLocal, que declara una
variable local l e imprime fmt.Println(l). Luego, printLocal imprime la
variable global g, fmt.Println(g). Aunque g no se definió en printLocal,
podría acceder a ella debido a que se declaró en un alcance global.
Por último, la función main imprime g también.
import "fmt"
var g = "global"
func printLocal() {
l := "local"
fmt.Println(l)
}
func main() {
fmt.Println(l)
}
Veamos otro ejemplo en el que usamos el mismo nombre de variable para una variable global y una local:
package main
import "fmt"
var num1 = 5
func printNumbers() {
num1 := 10
num2 := 7
fmt.Println(num1)
fmt.Println(num2)
}
func main() {
printNumbers()
fmt.Println(num1)
}
En este programa, declaramos la variable num1 dos veces. Primero,
declaramos num1 en el ámbito global, var num1 = 5, y otra vez dentro
del alcance local de la función printNumbers, num1 := 10. Cuando
imprimimos num1 desde el programa main, vemos el valor 5 impreso.
Esto se debe a que main solo detecta la declaración de variable global.
Sin embargo, cuando imprimimos num1 de la función printNumbers,
esta detecta la instrucción local e imprime el valor 10. Aunque
printNumbers crea una nueva variable llamada num1 y le asigna un
valor de 10, esto no afecta a la instancia global de num1 con el valor 5.
Al trabajar con variables, también deberá tener en cuenta las partes
de su programa que necesitarán acceso a cada variable y adoptar una
variable global o local correspondiente. En diferentes programas de
Go, verá que las variables locales son normalmente más comunes.
Constantes
Las constantes son como variables, con la excepción de que no pueden modificarse una vez
declaradas. Las constantes son útiles para definir un valor que se usará más de una vez en su
programa, pero que no debería poder cambiar.
Por ejemplo, si queremos declarar la tasa impositiva para un sistema de carritos de compras,
podríamos usar una constante y luego calcular los impuestos en diferentes áreas de nuestro
programa. En algún momento del futuro, si el impuesto se modifica solo deberemos cambiar
ese valor en un punto de nuestro programa. Si usamos una variable, es posible que
cambiemos el valor accidentalmente en algún lugar de nuestro programa, lo que provocaría
un cálculo inadecuado.
Para declarar una constante, podemos usar la siguiente sintaxis:
func main() {
hora := 24
minuto := int32(60)
fmt.Println(hora * año)
fmt.Println(minuto * año)
fmt.Println(minuto * bisiesto)
}
Interfaces
Escribir código flexible, reutilizable y modular es crucial para desarrollar
programas versátiles. Trabajar de esta forma garantiza que se pueda facilitar el
mantenimiento del código evitando la necesidad de realizar el mismo cambio
en varios puntos. La forma en que esto se consigue varía según el lenguaje. Por
ejemplo, inheritance es un enfoque común que se utiliza en lenguajes como
Java, C++ y C#, entre otros.
Los desarrolladores también pueden alcanzar esos objetivos de diseño a través
de la composición. La composición es una alternativa para combinar objetos o
tipos de datos y formar otros más complejos. Este es el enfoque que Go utiliza
para promover la reutilización del código, la modularidad y la flexibilidad. Las
interfaces de Go proporcionan un método para organizar composiciones
complejas y aprender a usarlas le permitirá crear código común y reutilizable.
Definir un comportamiento
Una de las principales implementaciones de la composición es el uso
de interfaces. Una interfaz define un comportamiento de un tipo. Una
de las interfaces que más se usan en la biblioteca estándar de Go es
fmt.Stringer:
import "fmt"
func main() {
a := Articulo{
Titulo: "Explicación del uso de interfaces en Go",
Autor: "Víctor Andrade Soto",
}
fmt.Println(a.String())
}
Lo primero que hacemos es crear un nuevo tipo llamado Articulo. Este
tipo tiene un campo Titulo y un campo Autor, y ambos son de la
cadena de tipo de datos:
main.go
...
type Article struct {
Title string
Author string
}
...
A continuación, definimos un método llamado String en el tipo
Articulo. El método String mostrará una cadena que representa el tipo
Articulo:
main.go
...
func (a Articulo) String() string {
return fmt.Sprintf("La %q ha sido descrita por %s.", a.Titulo,
a.Autor)
}
...
A continuación, en nuestra función main, creamos una instancia del tipo
Articulo y la asignamos a la variable llamada a. Proporcionamos los valores
de : "Explicación del uso de interfaces en Go“ para el campo Titulo y "Víctor
Andrade Soto“ para el campo Autor:
main.go
...
a := Articulo{
Titulo: "Explicación del uso de interfaces en Go",
Autor: "Víctor Andrade Soto",
}
...
A continuación, imprimimos el resultado del método String invocando
fmt.PrintIn y pasando el resultado de la invocación del método
a.String():
...
fmt.Println(a.String())
Hasta ahora no usamos una interfaz, pero creamos un tipo que tuvo
un comportamiento. Ese comportamiento coincidió con la interfaz
fmt.Stringer. A continuación, veremos la forma de usar ese
comportamiento para hacer que nuestro código sea más reutilizable.
Definir una interfaz
Ahora que nuestro tipo está definido con el comportamiento
deseado, podemos ver la forma de usar ese comportamiento.
Antes de hacer eso, sin embargo, veremos lo que deberíamos hacer si
deseáramos invocar el método String desde el tipo Articulo en una
función:
En este código, añadimos una nueva función llamada Imprimir que toma un Articulo como
argumento. Observe que lo único que la función Imprimir hace es invocar el método String.
func main() {
a := Articulo{
Titulo: "Explicación del uso de interfaces en Go",
Autor: "Víctor Andrade Soto",
}
Imprimir(a)
}