Simple, reliable, and efficient software, 2009
Index
Básico
- ¿Qué es Go?
- Descargar e instalar
- Hola mundo
- gofmt.exe
- Packages - import
- Exported names
- Funciones
- Variables
- Declaraciones de variables cortas :=
- Tipos de datos básicos
- Strings
- Arrays
- Slices
- Conversiones de Tipos de datos
- Inferencia de tipo
- Constantes
- fmt.Println
- go build
- Blank identifier _
- Printf
- Scanln
- Condicional if
- Condicional switch
- Flow control - control de flujo (Repetido/Iterado/ciclos)
- goto
- Defer
- Pointers (apuntadores)
- Structs
- Maps (par clave-valor)
- Paquete time
- Range
- Métodos
- Panic
- Concurrencia
- Paralelismo
- Channels
- Testing - Pruebas
- JSON
- Package http
- HTTP server
- Bibliotecas de funciones como paquetes
- Funciones como métodos
- Interfaces
- Manejo de errores
- io/ioutil
Go
¿Qué es Lenguaje Go?
Go es un lenguaje de programación moderno que se creó pensando en la web.
Go sirve para multiples casos, algunos de los mas comunes son:
- Crear scripts para el sistema
- Backend / APIs RESTful
- Sockets
Go es expresivo, conciso, limpio y eficiente.
Sus mecanismos de concurrencia facilitan la escritura de programas que aprovechan al máximo las máquinas multinúcleo y en red, mientras que su novedoso sistema de tipos permite la construcción de programas flexible y modular.
Go compila rápidamente en código de máquina pero tiene la conveniencia de la recolección de basura y el poder de la reflexión en tiempo de ejecución.
Es un lenguaje de programación compilado, rápido, concurrente, imperativo, estructurado, orientado a objetos, tipado estáticamente que se siente como un lenguaje interpretado dinámicamente tipado.
Organizado con paquetes y los paquetes tienen funciones. Una aplicación tiene su propio paquete, siempre llamado main, y también tiene la función principal que es llamada automáticamente en tiempo de ejecución cuando la aplicación se inicia.
Con Go, no hay una máquina virtual externa, por lo que el tiempo de ejecución debe estar vinculado estáticamente a cada aplicación.
Descargar e instalar
Descarga y sigue los pasos para la instalación de: Go
Una vez instalado prueba el siguiente comando:
- package main. Declare un paquete principal (un paquete es una forma de agrupar funciones).
El paquete principal tiene un significado especial en Go y hará que su código se compile para un ejecutable y no para el paquete.
Un programa completo se crea vinculando un único paquete no importado llamado paquete principal con todos los paquetes que importa, de forma transitiva.
El paquete principal debe tener el nombre de paquete main y declarar una función main que no toma argumentos y no devuelve ningún valor.
La ejecución del programa comienza inicializando el paquete principal y luego invocando la función main.
Cuando la invocación de esa función regresa, el programa se cierra. No espera a que se completen otras rutinas-go (no principales). - Importe el popular paquete fmt que contiene funciones para formatear texto, incluida la impresión en la consola.
Este paquete es uno de los paquetes de biblioteca estándar que recibió cuando instaló Go.
El paquete fmt implementa E/S formateado con funciones análogas a printf y scanf de C.
La mayor parte del código que utilizará estará en paquetes. - Implemente una función main para imprimir un mensaje en la consola.
Una función main se ejecuta de forma predeterminada cuando ejecuta código en el archivo.
Con un editor de texto escribe y almacena el archivo con la extensión .go
Para ejecutar el programa utiliza el comando go run:
Eso compila la aplicación y crea un ejecutable temporal en su disco, y luego ejecuta la aplicación. Pero el nuevo ejecutable no está en el mismo directorio.
gofmt.exe
Utiliza tabs para la sangría y espacios en blanco para la alineación. La alineación asume que un editor está usando una fuente de ancho fijo.
Sin una ruta explícita, procesa la entrada estándar. Dado un archivo, opera en ese archivo; dado un directorio, opera en todos los archivos .go en ese directorio, de forma recursiva. (Los archivos que comienzan con un punto se ignoran). De forma predeterminada, gofmt imprime las fuentes reformateadas en una salida estándar.
Es necesario usar el switch -w para que se almacenen los cambios realizados, de otra forma no se aplica el formato.
go build
Para crear un archivo ejecutable (exe en el caso de windows) use el comando:
Si se crea con éxito no se se obtiene una notificación de salida en la línea de comando.
Liste el contenido del directorio para verificar que se ha generardo el archivo ejecutable (exe en el caso de windows). Note que el archivo ejecutable será en tamaño mayor al archivo.go (código fuente) esto es porque se incorpora lo necesario para su ejecución.
Verifique que su sistema de seguridad le permita crear archivos ejecutables
Packages - import
Cada programa de Go se compone de paquetes.
Los programas comienzan a ejecutarse en el paquete main.
Los programas utilizan los paquetes con rutas de importación.
Por convención, el nombre del paquete es el mismo que el último elemento de la ruta de importación.
Para hacer uso de funciones contenidas en paquetes de la biblioteca estándar incluidas cuando instaló Go, utilice import seguido y entre comillas dobles del nombre del paquete:
Si utiliza más de un paquete estos deberán estar contenidos entre parentesis: (o bien un import por cada paquete)
Por ejemplo para utilizar funciones de fecha y hora, puede importar el paquete time y para imprimir fmt
Instalación de paquetes
Para instalar paquetes de terceros utilice el comando go get, que instala una dependencia a la vez e instala la última versión del paquete.
go get <ubicaciónPaquete>
Al incluir la biblioteca en la sección de import un paquete puede tener un nombre diferente al del directorio en el que se encuentra, así que puede darle un nombre.
mipaquete "nombredelpaquete"
Instalado el paquete, solo podemos usar funciones y variables que comiencen con una letra mayúscula en este paquete. Todo lo demás es privado y solo se puede usar desde el interior del paquete.
Algunos paquetes se basan en otros paquetes
Construido el programa, todos los paquetes de los que depende se empaquetan en el ejecutable, lo cual significa que cuando implementa un programa, no necesita ningún otro paso de instalación.
Exported names
En Go, un nombre se exporta si comienza con una letra mayúscula.
Al importar un paquete, solo puede hacer referencia a sus nombres exportados.
Cualquier nombre "no exportado" no es accesible desde fuera del paquete.
Funciones
Las funciones dan modularidad y reutilización de código.
Una función puede tener cero o más argumentos.
Puede definir funciones personalizadas y organizarlas en paquetes.
Si la definición de función y el código que las invoca están en el mismo paquete, el nombre de la función puede ser superior o inferior.
No hay sobrecarga de funciones o métodos, por lo que cada nombre de función debe tener un número específico de argumentos.
No puede tener dos versiones de la función con diferentes números o tipos de argumentos.
No puede tener funciones con el mismo nombre dentro del mismo paquete, incluso si difieren en sus firmas.
Las funciones que comienzan con un carácter inicial en minúscula, las hace privadas para el paquete actual, es decir, no se exportan para su uso fuera de este paquete.
Las funciones que comienzan con un carácter inicial a mayúsculas, las hace públicas, accesible para el resto de la aplicación
Para crear una función se emplea la keyword (palabra reservada) func seguido del nombre de la función y entre parentesis el nombre del argumento seguido de su tipo de dato, separado cada argumento por una coma (,) seguido del tipo de dato que devuelve la función y si devuelve más de un resultado son separados por una coma (,)
El cuerpo de la función va contenido entre llaves { }
Cuando dos o más parámetros de función nombrados consecutivos comparten un tipo, puede omitir el tipo de todos menos el último.
Múltiples resultados
Una función puede devolver cualquier número de resultados.
La capacidad de devolver múltiples valores es esencial en un lenguaje que no tiene una sintaxis estructurada convencional de manejo de excepciones.
En vez de lanzar una excepción y manejarla en un bloque try-catch, la función devuelve el valor esperado y el error. El programador evalua los valores devueltos y decide qué hacer.
Valores de retorno con nombre
Se pueden nombrar los valores de retorno de Go. Si es así, se tratan como variables definidas en la parte superior de la función.
Estos nombres deben usarse para documentar el significado de los valores devueltos.
"Naked" return
Una declaración de retorno sin argumentos devuelve los valores de retorno nombrados. Esto se conoce como un regreso "desnudo".
Las declaraciones de retorno naked deben usarse solo en funciones cortas. Pueden dañar la legibilidad en funciones más largas.
Diferencia entre una función no naked y una función naked
Ejemplos de funciones
Function values
Las funciones también son valores. Pueden transmitirse como otros valores.
Los valores de función se pueden utilizar como argumentos de función y valores de retorno.
Go tiene algo llamado panic, que es algo similar a las excepciones en otros idiomas.
El uso de "pánico" se desaconseja en Go y se considera un anti-patrón.
La forma de señalar un error es devolverlo.
Variables
La instrucción var declara una lista de variables; como en las listas de argumentos de funciones, el tipo es el último.
Una instrucción var puede estar a nivel de paquete o función.
Para declarar una variable, use var seguido del nombre de la variable, el tipo de dato y puede ser inicializada usando el signo igual (=) y el valor correspondiente.
Variables con inicializadores
Una declaración var puede incluir inicializadores, uno por variable.
Si hay un inicializador, se puede omitir el tipo; la variable tomará el tipo de inicializador.
Zero values
Las variables declaradas sin un valor inicial explicito, reciben el valor zero
El valor zero es:
- 0 para tipos numéricos
- false para tipos booleanos
- "" (El string vacio) para tipos strings.
- var palabra reservada
- Nombre de la variable (más de una variable deberá ser separada por comas)
- Tipo de dato
- = operador de asignación y valor inicial (opcional)
Declaración implicita de variables
- Nombre de la variable
- := operadores de asignación corta y valor inicial
El tipo de variable aún se determina durante la compilación y sigue siendo estático, y no se puede cambiar en tiempo de ejecución.
Nota: una vez declarada una variable la asignación de valor es mediante el operador igual =
Declaraciones de variables cortas :=
Dentro de una función, la declaración de asignación corta := se puede usar en lugar de una declaración var con tipo implícito.
Fuera de una función, cada declaración comienza con una palabra clave (var, func, etc.) y, por lo tanto, la construcción := no está disponible.
Tipos de datos básicos
- bool
- string
- int int8 int16 int32 int64
- uint uint8 uint16 uint32 uint64 uintptr
- byte. alias for uint8
- rune. alias for int32 represents a Unicode code point
- float32 float64
- complex64 complex128
Strings
String en Go es, un segmento de bytes de solo lectura, para definir un string se encierra entre comillas dobles.
Puede acceder a bytes individuales de un string con corchetes string[index]
No se puede cambiar el valor de una parte de un string una vez que ha sido creado, en go son inmutables.
Uint8 en go es un byte
len(string) esta función obtiene el número de bytes en el string.
Para acceder al valor del byte se utilizan Slices [ ]
Para concatenar strings se usa el signo +
Es posible construir varias cadenas de línea encerradas entre tildes `
Paquete "strings"
El paquete strings contiene funciones a manera de utilerias para el manejo de strings.
Arrays
Un Array o arreglo es una colección ordenada de valores
En Go es mejor usar slices que arreglos para representar colecciones ordenadas de valores.
El tipo [n]T es un array de n valores de tipo T
Para declarar un array:
- Ingrese la palabra reservada var
- Designe un nombre para la variable
- Entre corchetes coloque el número de elementos que contendrá el array
- Declare el tipo de dato de los valores contenidos en el array
La longitud de un Array es parte de su tipo, por lo que no se puede cambiar el tamaño de los arreglos. Go proporciona una forma conveniente de trabajar con arrays.
Slices
Un slice es una secuencia de elementos.
Un array tiene un tamaño fijo. Un slice, por otro lado, es una vista flexible de tamaño dinámico dentro de los elementos de un array.
El tipo []T es un slice con elementos de tipo T
Un slice en Go es una capa de abstracción que se encuentra encima de un array.
Cuando declara un slice, en tiempo de ejecución crea un arreglo subyacente al slice, asigna la memoria requerida y luego devuelve el slice solicitado.
Para definir un slice escriba el nombre seguido de una declaración corta := escriba corchetes [] seguido de su tipo de dato y coloque entre llaves {} y separados por comas los valores del slice
La siguiente expresión crea un slice que incluye los elementos 1 a 3 de a:
Un slice se forma especificando dos índices, un límite inferior y uno superior, separados por dos puntos.
Un slice no almacena ningún dato, solo describe una sección de un array subyacente.
Cambiar los elementos de un slice modifica los elementos correspondientes de su array subyacente.
Otros slices que comparten el mismo array subyacente verán esos cambios.
Para acceder a los valores del slice use corchetes y el índice, recuerde que el índice comienza en cero [idx]
Puede acceder también a los valores del slice usando rangos, donde es posible omitir el inicio o fin del rango [s:], [:e]
La palabra reservada range obtiene el rango de índices del slice
append(slice, "new") agrega un elemento al final del slice
func append(s []T, vs ...T) []T
El primer parámetro s de append es un slice de tipo T, y el resto son valores de T para agregar al slice.
El valor resultante de append es un slice que contiene todos los elementos del slice original más los valores proporcionados.
Si el arreglo de respaldo de s es demasiado pequeña para ajustarse a todos los valores dados, se asignará un arreglo más grande. El slice devuelto apuntará a el arreglo recién asignado.
Slice literals
Un literal de slice es como un literal de array sin la longitud.
Este es un literal de array:
[3]bool{true, true, false}
Y esto crea el mismo array que el anterior, luego crea un slice que hace referencia a este:
[]bool{true, true, false}
Slice defaults
Puede omitir los límites infrerior o superior para usar sus valores predeterminados en su lugar.
El valor predeterminado es cero para el límite inferior y la longitud del slice para el límite superior.
Para el array
var a [10]int
Estas expresiones de corte son equivalentes:
a[0:10]
a[:10]
a[0:]
a[:]
Slice: Longitud y capacidad
Un slice tiene tanto una longitud como una capacidad.
La longitud de un slice es el número de elementos que contiene.
La capacidad de un slice es el número de elementos del array subyacente, contando desde el primer elemento del slice.
La longitud y la capacidad de un segmento s se pueden obtener utilizando las expresiones len (s) y cap (s).
Puede extender la longitud de un slice volviéndo a re-slice, siempre que tenga la capacidad suficiente.
Nil slices
El valor cero de un slice es nil
Un slice nil tiene una longitud y capacidad de 0 y no tiene un array subyacente.
Creando un slice con la función make
Los slices pueden ser creados con la función make. Así es como se crean arrays de tamaño dinámico.
La función make aloja un array cero y regresa un slice que se refiere a este array.
s := make([]int, l) //len(s) es igual a l.
Para especificar una capacidad indique este como tercer argumento:
s := make([]int, l, c) //len(s) es igual a l y cap(s) es igual a c.
Slices de slices
Slices pueden contener cualquier tipo, incluyendo otros slices
Conversiones de tipos
La expresión T(v) convierte el valor v al tipo T.
Inferencia de tipo
Cuando se declara una variable sin especificar un tipo explícito (ya sea utilizando la sintaxis := o var = sintaxis de expresión), el tipo de la variable se infiere del valor del lado derecho.
Cuando se escribe el lado derecho de la declaración, la nueva variable es del mismo tipo:
Pero cuando el lado derecho contiene una constante numérica sin tipo, la nueva variable puede ser un int, float64 o complex128 dependiendo de la precisión de la constante.
Constantes
Una constante es un valor que nunca cambia.
Puede utilizar la escritura explícita o implícita.
Escritura explícita:
- Comienza con la palabra clave const
- Ingrese el nombre de la variable
- Tipo de datos que desea usar
- Asigna su valor con el operador igual =
- Comienza con la palabra clave const
- Ingrese el nombre de la variable
- Asigna su valor con el operador igual =
Las constantes se declaran como variables, pero con la palabra clave const.
Las constantes pueden ser valores de caracteres, cadenas, booleanos o numéricos.
Las constantes no se pueden declarar utilizando la sintaxis :=
Constantes numéricas
Las constantes numéricas son valores de alta precisión.
Una constante sin tipo toma el tipo que necesita su contexto.
fmt.Println
Esta función imprime formatos utilizando los formatos predeterminados para sus operandos y escribe en la salida estándar.
Siempre se agregan espacios entre operandos y se agrega una nueva línea. Devuelve el número de bytes escritos y cualquier error de escritura encontrado.
Blank identifier _
El identificador en blanco proporciona una forma de ignorar los valores del lado derecho en una asignación:
El identificador en blanco está representado por el carácter de subrayado _.
Sirve como un marcador de posición anónimo en lugar de un identificador regular (no en blanco) y tiene un significado especial en declaraciones, como operando y en asignaciones.
Printf
La función Printf formatea de acuerdo con un especificador de formato y escribe en la salida estándar.
Devuelve el número de bytes escritos y cualquier error de escritura encontrado.
Ejemplos de Verbos:
- %v el valor en un formato predeterminado al imprimir estructuras, el indicador más (%+v) agrega nombres de campo
- %#v una representación de sintaxis Go del valor
- %T una representación de sintaxis Go del tipo de valor
- %% un signo de porcentaje literal; no consume ningún valor
Scanln
La función Scanln es similar a Scan, pero deja de escanear en una nueva línea y después del elemento final debe haber una nueva línea o EOF.
NewReader devuelve un nuevo Reader cuyo búfer tiene el tamaño predeterminado.
ReadString lee hasta la primera aparición de delim en la entrada, devolviendo una cadena que contiene los datos hasta el delimitador incluido.
Si ReadString encuentra un error antes de encontrar un delimitador, devuelve los datos leídos antes del error y el error en sí (a menudo io.EOF).
ReadString devuelve err != nil si y solo si los datos devueltos no terminan en delim.
Para usos simples, un escáner puede ser más conveniente.
func (b * Reader) ReadString (delimitar byte) (string, error)
Condicional if
Una condicional if permite la ejecución de un bloque de código, dado que evalua una condición cuyo valor solo puede ser: verdadero o falso.
Si la condición se cumple, el bloque de código se ejecuta.
La condición a evaluar no va entre paréntesis.
Las llaves { } son obligatorias.
La palabre reservada else se coloca en la misma línea que la llave de cierre anterior. Si no es así, obtendrá un error de sintaxis .
Su sintaxis es:
La condición evalua una operación lógica como:
- true Verdadero
- false Falso
- > Mayor que
- >= Mayor o igual que
- < Menor que
- <= Menor o igual que
- == Igual
- != Diferente
- && Y
- || O
La instrucción if puede comenzar con una instrucción corta para ejecutar antes de la condición.
Las variables declaradas solo están dentro del alcance hasta el final del if.
else if
Uno de los objetivos de Go es reducir la cantidad de escritura.
Condicional switch
Una instrucción switch es una forma más corta de escribir una secuencia de declaraciones if - else.
Go solo ejecuta el caso seleccionado, no todos los casos siguientes.
Los Switch-cases evalúan los casos de arriba a abajo, deteniéndose cuando un caso tiene éxito.
La declaración "break" que se necesita al final de cada caso en esos idiomas se proporciona automáticamente en Go.
La declaración break que se necesita al final de cada caso en otros lenguajes se proporciona automáticamente en Go.
Los Switch-cases en Go no necesitan ser constantes y los valores involucrados no necesitan ser enteros.
Una condicional switch permite tener múltiples casos de código a ejecutar, solo un caso se podrá ejecutar si al evaluar una condición su valor coincide con la condición del caso, de no coincidir con alguno de los casos se puede ejecutar el caso por defecto.
Su sintaxis es:
Existe una variante donde switch no tiene una condición lógica contra la cual evaluar, pero la condición se evalua en cada caso.
Esta construcción puede ser una forma limpia de escribir largas cadenas if-then-else.
Switch sin una condición es lo mismo que switch true.
fallthrough
La instrucción fallthrough transfiere el control a la primera instrucción de la siguiente cláusula de caso en una expresión instrucción "switch".
Puede usarse solo como la declaración final no vacía en dicha cláusula.
Vea un ejemplo aquí
Flow control - control de flujo (Repetido/Iterado/ciclos)
Una forma de ejecutar instrucciones de código más de una vez es a través de la repetición o iteración, en inglés se conoce como loop.
For
Go tiene solo una construcción de repetición, el iterado for.
El iterado for básico tiene tres componentes separados por punto y coma (;)
- La instrucción init o inicial: ejecutada antes de la primera iteración.
- La condición de ejecución: evaluado antes de cada iteración.
- La declaración de incremento: se ejecuta al final de cada iteración.
El ciclo dejará de iterarse una vez que la condición booleana se evalúe como falsa.
for <init statement>; <condition expression>; increment {
instruction
}
Las declaraciones inicial e incremental son opcionales.
For (while)
En Go existe un for sin punto y coma (;) (y sin declaraciones inicial e incremental).
La declaración de incremento estará en el cuerpo del For .
Si omite la condición de ejecución, se repite para siempre, por lo que un ciclo infinito se expresa de forma compacta.
goto
La palabra reservada goto sirve para continuar la secuencia de ejecución del código en una etiqueta determinada que debe estar en el ámbito de visibilidad desde donde se este haciendo referencia, si esta no es visible se genera un error y se indicará que no esta definida
Para usar este mecanismo defina la etiqueta en donde sea necesaria y sea visible en la ejecución del código, para ello defina un nombre de etiqueta seguido de dos puntos
nombreEtiqueta:
Para indicar que la ejecución de código continue en la etiqueta definida utilice la palabra reservada goto y a continuación el nombre de la etiqueta
goto nombreEtiqueta
Defer
Una declaración defer pospone la ejecución de una función hasta que regresa la función circundante.
Difiere la ejecución de un bloque de código hasta que todo lo demás en la función actual haya finalizado.
Cada vez que llama a la instrucción defer, agrega una instrucción a una pila, y cuando se ejecutan las instrucciones diferidas, se manejan en el último en entrar, primero en salir, conocido como LIFO.
Los argumentos de la llamada diferida se evalúan inmediatamente, pero la llamada a la función no se ejecuta hasta que vuelve la función circundante.
Stacking defers
Las llamadas a funciones defer se insertan en una pila. Cuando una función regresa, sus llamadas diferidas se ejecutan en el orden: último en entrar, primero en salir.
Para asegurarse de que un recurso esté cerrado, use defer.
Pointers (apuntadores)
Un pointer contiene la dirección de memoria de un valor.
El tipo *T es un pointer a un valor de T. Su valor cero es nulo, cuando se declara en este momento no apunta a nada. Entonces, decimos que es nulo.
var apuntador *int
El operador & genera un puntero a su operando.
El ampersand significa conectar el puntero a la variable.
El operador * denota el valor subyacente del apuntador.
Structs
Una struct es una colección de campos.
Para acceder a los campos de una estructura es mediante la notación punto.
Maps (par clave-valor)
Un map es una estructura de datos donde las claves apuntan a los valores.
Un mapa es una colección desordenada de pares clave-valor.
Un mapa es esencialmente una tabla hash que le permite almacenar colecciones de datos y luego encontrar arbitrariamente elementos en la colección por sus claves.
En go, las claves deben ser del mismo tipo y los valores deben ser del mismo tipo.
Es necesario tener una coma al final de la última línea de los items.
Para validar la existencia de una clave puede acceder al par de valores que regresa clave-valor
Insertar o actualizar un elemento en el map
mapName[key] = valor
Obtener el valor del elemento en el map
varName = mapName[key]
Eliminar un elemento en el map
delete(mapName, key)
Evaluar que existe una clave con una asignación de dos valores:
valor, ok = mapName[key]
Si la clave existe en el map, ok es verdadero. Si no existe la clave es falso.
Si la clave existe en el map, entonces el valor del elemento es cero para el tipo de elemento del mapa.
Nota: Si aún no se han declarado valores y elementos, puede utilizar una forma de declaración corta:
valor, ok := mapName[key]
Un mapa asigna claves a valores.
El valor cero de un mapa es nil.
Un mapa nil no tiene claves, ni se pueden agregar claves.
La función make devuelve un mapa del tipo dado, inicializado y listo para usar.
La función new() asigna pero no inicializa la memoria. Cuando asigna un mapa obtendrá una dirección de memoria que indica la ubicación del mapa, pero el mapa tiene almacenamiento de memoria en cero
La función make() asigna e inicializa memoria Obtendrá la dirección de memoria, tal como lo hace con new(), pero el almacenamiento no es cero y está listo para aceptar valores.
Ordenar por claves de un mapa
Paquete time
El paquete time proporciona funcionalidad para medir y mostrar el tiempo.
Los cálculos calendáricos siempre asumen un calendario gregoriano, sin segundos intercalares.
Range
La forma de range del ciclo for itera sobre un slice o map.
Cuando se recorre un slice, se devuelven dos valores para cada iteración.
- El primero es el índice
- El segundo es una copia del elemento en ese índice.
Es posible omitir el índice o valor, asignandolo a _.
Si solo desea el índice, puede omitir la segunda variable.
Métodos
Go no tiene clases. Sin embargo, puede definir métodos en tipos.
Un método es una función con un argumento de receptor especial.
El receptor aparece en su propia lista de argumentos entre la palabra clave func y el nombre del método.
Es posible definir métodos en estructuras.
Es similar a la definición de una función solo hay que anteponer el recepor que es un pointer a la estructura antes del nombre del método.
Panic
Para el manejo de errores Go tiene una función incorporada panic(err) para casos en los que hay un error que no puede manejar pero que deben ser señalados causando pánico.
Para señalar errores es devolver un valor de error.
Se desaconseja el uso del panic en Go.
Go, está diseñado para la simultaneidad.
La concurrencia es la composición de procesos que se ejecutan de forma independiente.
La concurrencia consiste en lidiar con muchas cosas a la vez.
El paralelismo es la ejecución simultánea de cálculos (posiblemente relacionados).
El paralelismo consiste en hacer muchas cosas a la vez.
Channels
Los canales son tuberías unidireccionales escritas. Se envían valores por un extremo y se reciben por el otro. Si intenta recibir y no hay nada en el canal, se bloqueará.
Tipos de canales
- Con búfer
Cada canal de búfer tiene una capacidad. Si envía al canal de búfer hasta que se llene la capacidad, no se bloqueará.
Una vez completada la capacidad, se bloqueará el ascenso a un canal. - Sin búfer
Cuando empuja un valor a través de un canal sin búfer, se bloqueará hasta que alguien lo reciba por otro lado.
Testing - Pruebas
La el paquete testing proporciona soporte para pruebas automatizadas de paquetes Go.
Está diseñado para usarse junto con el comando go test, que automatiza la ejecución de cualquier función del formulario.
Dentro de estas funciones, utilice los métodos: Error, Fail o relacionados para señalar la falla.
Go tiene un framework de pruebas integrado.
Para escribir un nueva suite de pruebas:
- El nombre de un archivo de pruebas en go termina con el sufijo _test y la exensión .go que contenga las funciones de TestXxx.
- Coloque el archivo en el mismo paquete que el que se está probando.
- El archivo se excluirá de las compilaciones de paquetes normales, pero se incluirá cuando se ejecute el comando go test.
- Importe la biblioteca "testing"
- Cree funciones de pruebas con el prefijo Test (la primera letra es Mayúscula) y recibe un argumento que es un indicador para probar la estructura T.
- Si hay un error, que no se espera, se usa t.Fatalf() que detendrá la ejecución aquí mismo e imprimirá el mensaje de error y el error.
- Se usa Fatalf() para imprimir el error.
- Para ejecutar la prueba use el comando go Test
JSON
El paquete json implementa la codificación y decodificación de JSON como se define en RFC 7159.
JSON (JavaScript Object Notation) es un formato de intercambio de datos simple.
Se utiliza con mayor frecuencia para la comunicación entre los servidores web y los programas JavaScript que se ejecutan en el navegador.
Es posible ordenar una versión codificada en JSON de una estructura usando json.Marshal:
b, err := json.Marshal(struct)
Si todo está bien, err será nil y b será un byte [] que contiene estos datos JSON
b == []byte(`{notación_json}`)
Para decodificar datos JSON usamos la función Unmarshal.
Primero cree una variable donde se almacenarán los datos decodificados
var nombre_variable Tipo
Invoque json.Unmarshal, pasándole un []byte de datos JSON y un puntero a la variable
err: = json.Unmarshal (b, & nombre_variable) Si b contiene JSON válido que cabe en nombre_variable, después de la llamada, err será nil y los datos de b se habrán almacenado en la estructura nombre_variable, como si fuera una asignación como:
nombre_variable = Estructura{
Field_1: value_type,
Field_1: value_type,
Field_1: value_type,
}
Unmarshal decodificará solo los campos que pueda encontrar en el tipo de destino, solo se completarán los campos de la estructura y se ignorarán los campos que no existen en esta.
Este comportamiento es particularmente útil cuando desea seleccionar solo algunos campos específicos de un blob JSON grande. También significa que los campos no exportados en la estructura de destino no se verán afectados por Unmarshal.
Package http
El paquete http proporciona implementaciones de cliente y servidor HTTP.
resp, err := http.Get("http://example.com/")
if err != nil {
// handle error
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
// ...
El cliente debe cerrar el cuerpo de la respuesta cuando termine con él.
El paquete HTTP le permite realizar solicitudes y enviar datos a hosts remotos, y también le permite crear aplicaciones de servidor HTTP que escuchan y responden solicitudes.
Get, Head, Post y PostForm realizan solicitudes HTTP (o HTTPS):
resp, err := http.Get("http://example.com/")
...
resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf)
...
resp, err := http.PostForm("http://example.com/form", url.Values{"key": {"Value"}, "id": {"123"}})
Otra manera:
HTTP server
Con Go puede ser muy fácil crear una aplicación de servidor HTTP simple.
Con el mismo paquete "net/http" que se utiliza para realizar solicitudes web, se puede ejecutar una aplicación en una computadora host que escucha y responde a solicitudes de otros dispositivos conectados a la web.
En el siguiente ejemplo se crea una estrtuctura con el método "serveHTTP", la firma, o sintaxis, de este método la define el paquete "net/http".
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request)
(Formatea Fprint usando los formatos predeterminados para sus operandos y escribe en w.
Se agregan espacios entre operandos cuando ninguno es una cadena.
Devuelve el número de bytes escritos y cualquier error de escritura encontrado.)
ListenAndServe inicia un servidor HTTP con una dirección y un controlador determinados.
El controlador suele ser
nil, lo que significa utilizar DefaultServeMux.
Handle y HandleFunc agregan controladores a DefaultServeMux.
El primer argumento de la función es el puerto personalizado que puede ser cualquier número de puerto que no esté en uso en la máquina.
Para probar, en su navegador acceda a localhost:4321
Para detener la ejecución del programa: CTRL + C
El siguiente código inicia un servidor http. Para probar, en su navegador acceda a localhost:8080/hola
Para detener el servidor http, CTRL + C
Bibliotecas de funciones como paquetes
Es posible tener un conjunto de funciones en paquetes y declardos en archivos de código fuente separados, y de esta manera volverlos a usar en otros programas.
Funciones como métodos
Go admite el concepto de métodos, que son esencialmente funciones y pertenecen a alguna estructura u otro tipo.
En Go, un método es miembro de un tipo.
Interfaces
Una interfaz es una colección de métodos y cada tipo implementa todos los métodos en la interfaz.
Un método debe coincidir en nombre y también en firma, parámetros y valor de retorno.
Si se implementan todos los métodos definidos en una interfaz, entonces es una implementación de esa interfaz.
Las relaciones de interfaz y tipo están implícitas en la presencia de los métodos.
Para definir una interfaz use la palabra reservada interface.
Manejo de errores
En Go un error es una instancia de una interfaz que define un solo método, llamado Error, y ese método devuelve una cadena y esa cadena es el mensaje de error.
Cuando error es nil significa que no hay error.
Existe un paquete llamado errors.
De clic aquí para ver el mecanismo en map
io/ioutil
Ejemplo de manejo de archivos: