Verificados capitulos 1 y 2

This commit is contained in:
ma0
2016-12-14 21:50:21 -05:00
parent f94c6fce61
commit 85d7878ae0
14 changed files with 217 additions and 216 deletions

View File

@@ -16,5 +16,5 @@ En este capítulo, te mostraremos cómo instalar y configurar tu propio ambiente
## Links
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección siguiente: [Instalación](01.1.md)

View File

@@ -28,21 +28,21 @@ En Windows, debes instalar MinGW antes para poder instalar gcc. No olvides confi
El equipo Go usa [Mercurial](http://mercurial.selenic.com/downloads/) para manejar su código fuente, por lo que debes instalar esta herramienta para poder bajar el código fuente de Go.
En este punto ejecuta los siguientes comandos para clonar el código fuente de Go y compilarlo. (Clonará el código fuente en tú directorio actual. Cambia tu ruta actual antes de continuar. Esto puede tomar algún tiempo.)
```
hg clone -u release https://code.google.com/p/go
cd go/src
./all.bash
```
Una instalación exitosa finalizará con el mensaje "ALL TESTS PASSED."
En Windows puedes lograr lo mismo ejecutando `all.bat`.
Si estas usando Windows el paquete de instalación establecerá tus variables de entorno automáticamente. En sistemas tipo Unix necesitas establecer estas variables de la siguiente manera. (Si tu versión de Go es mayor que 1.0 no debes establecer $GOBIN ya que estará relacionada automáticamente a tu $GOROOT/bin del que hablaremos en la sección siguiente)
```
export GOROOT=$HOME/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOROOT/bin
```
Si ves la siguiente información en tu pantalla, todo está listo.
![](images/1.1.mac.png?raw=true)
@@ -66,11 +66,11 @@ Si eres un usuario de Mac recomiendo fuertemente que bajes el paquete de 64-bits
Los usuarios de Linux pueden escribir `uname -a` en la terminal para ver la información del sistema.
Un sistema operativo de 64-bits mostrará lo siguiente:
```
<alguna descripción> x86_64 x86_64 x86_64 GNU/Linux
// algunas versiones como Ubuntu 10.04 mostrarán de la siguiente forma
x86_64 GNU/Linux
```
En cambio los sistemas operativos de 32-bits mostrarán:
<alguna descripción> i686 i686 i386 GNU/Linux
@@ -92,32 +92,32 @@ Ve a la [página de descarga](https://golang.org/dl/), escoge `go1.5.3.windows-3
### GVM
GVM es una herramienta de control de múltiples versiones de Go desarrollado por terceros, parecida a rvm para ruby. Es bien fácil de utilizar. Instala gvm escribiendo los siguientes comandos en tu terminal:
```
bash < <(curl -s https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)
```
Luego instalamos Go usando los siguientes comandos:
```
gvm install go1.0.3
gvm use go1.0.3
```
Cuando el proceso ha finalizado estamos listos.
### apt-get
Ubuntu es la versión de escritorio más popular de Linux. Utiliza `apt-get` para manejar paquetes. Podemos instalar Go usando los siguientes comandos.
```
sudo add-apt-repository ppa:gophers/go
sudo apt-get update
sudo apt-get install golang-stable
```
### Homebrew
Homebrew es una herramienta para manejar software comúnmente usada en la Mac. Simplemente escribe lo siguiente para instalar Go.
```
brew install go
```
## Links
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección anterior: [Configurando el entorno de Go](01.0.md)
- Sección siguiente: [$GOPATH y el ambiente de trabajo](01.2.md)

View File

@@ -5,9 +5,9 @@
Todos los comandos de Go dependen de una importante variable de entorno llamada $GOPATH. Favor notar que esta no es la variable $GOROOT que es la que muestra dónde Go está instalado. Esta variable apunta al ambiente de trabajo de Go en tu computadora (Yo uso esta ruta en mi computadora; si no tienes la misma estructura de directorios, por favor reemplaza por la que tengas).
En sistemas tipo Unix, la variable debe usar así:
```
export GOPATH=/home/apple/mygo
```
En Windows, necesitas crear una nueva variable de entorno llamada GOPATH, luego estable su valor a `c:\mygo` (Este valor depende dónde tu ambiente de trabajo esté ubicado)
Está bien tener más de una ruta de ambiente de trabajo en $GOPATH, pero recuerda que debes usar `:`(`;` en Windows) para separarlos. En este punto, `go get` guardará el contenido de tu primera ruta en $GOPATH.
@@ -22,17 +22,17 @@ En este libro, utilizo `mygo` cómo mi única ruta en $GOPATH.
## Directorio de paquetes
Crea archivos de código fuente de paquetes de la siguiente forma `$GOPATH/src/mymath/sqrt.go` (`mymath` es el nombre del paquete) ( ***El autor utiliza `mymath` cómo su nombre de paquete, el mismo nombre para el directorio que contiene los archivos de código fuente del paquete)
Crea archivos de código fuente de paquetes de la siguiente forma `$GOPATH/src/mymath/sqrt.go` (`mymath` es el nombre del paquete) ( **El autor utiliza `mymath` cómo su nombre de paquete, el mismo nombre para el directorio que contiene los archivos de código fuente del paquete**)
Cada vez que creas un paquete, deberías crear un nuevo folder en el directorio `src`. Los nombres de los directorios usualmente son los mismos que el paquete que vas a utilizar. Puedes tener directorios de múltiples niveles si lo deseas. Por ejemplo, si creas el directorio `$GOPATH/src/github.com/astaxie/beedb`, entonces la ruta del paquete sería `github.com/astaxie/beedb`. El nombre del paquete será el último directorio en tu ruta, que es `beedb` en este caso.
Ejecuta los siguientes comandos. (Ahora el autor mostrará unos ejemplos)
```
cd $GOPATH/src
mkdir mymath
```
Crea un nuevo archivo llamado `sqrt.go`, escribe el siguiente contenido en el archivo.
```
// Código fuente de $GOPATH/src/mymath/sqrt.go
package mymath
@@ -43,7 +43,7 @@ Crea un nuevo archivo llamado `sqrt.go`, escribe el siguiente contenido en el ar
}
return z
}
```
Ahora el directorio de mi paquete ha sido creado y su código ha sido escrito. Recomiendo que uses el mismo nombre para tus paquetes y sus directorios correspondientes y que los directorios contenga todo el código fuente del paquete.
## Compilar paquetes
@@ -54,24 +54,24 @@ Ya hemos creado nuestra paquete, pero cómo lo compilamos para propósitos prác
2. Ejecuta el comando de arriba, con la diferencia de que suministras el nombre del archivo como parámetro `go install mymath`.
Después de compilar podemos abrir el siguiente directorio.
```
cd $GOPATH/pkg/${GOOS}_${GOARCH}
// puedes ver que el archivo fue generado
mymath.a
```
Este archivo cuyo sufijo es `.a`, es el archivo binario de nuestro paquete. Cómo lo usamos?
Obviamente, necesitamos crear una nueva aplicación para utilizarlo.
Crea una nueva aplicación llamada `mathapp`.
```
cd $GOPATH/src
mkdir mathapp
cd mathapp
vim main.go
```
código
```
//$GOPATH/src/mathapp/main.go código fuente
package main
@@ -83,23 +83,23 @@ código
func main() {
fmt.Printf("Hello, world. Sqrt(2) = %v\n", mymath.Sqrt(2))
}
```
Para compilar esta aplicación necesitas cambiar al directorio de la aplicación que en este caso es `$GOPATH/src/mathapp`, luego ejecuta el comando `go install`. Ahora deberías ver un archivo ejecutable llamado `mathapp` que se ha generado en el directorio `$GOPATH/bin/`. Para correr este programa usa el comando `./mathapp`. Deberías de ver el siguiente contenido en tu terminal:
```
Hello world. Sqrt(2) = 1.414213562373095
```
## Instala paquete remotos
Go tiene una herramienta para instalar paquetes remotos, es el comando llamado `go get`. Soporta la mayoría de comunidades de código libre, incluyendo Github, Google Code, BitBucket y Launchpad.
```
go get github.com/astaxie/beedb
```
Puedes usar `go get -u …` para actualizar tus paquetes remotos e incluso instalará todas sus dependencias.
Esta herramienta usará diferente herramientas de control de versiones para las diferentes plataformas de código libre. Por ejemplo, `git` para Github y `hg` para Google Code. Debido a esto, debes instalar estas herramientas de control de versiones antes de usar `go get`.
Después de ejecutar los comandos anteriormente descritos, la estructura de directorios debería verse de la siguiente forma:
```
$GOPATH
src
|-github.com
@@ -110,7 +110,7 @@ Después de ejecutar los comandos anteriormente descritos, la estructura de dire
|-github.com
|-astaxie
|-beedb.a
```
Actualmente, `go get` clona el código fuente a la ruta $GOPATH/src, luego ejecuta `go install`.
Puedes usar paquetes remotos de la misma forma que usas paquetes locales.
@@ -120,7 +120,7 @@ Puedes usar paquetes remotos de la misma forma que usas paquetes locales.
## Estructura completa del directorio
Si has seguido todos los pasos anteriores, la estructura de tu directorio se debería ver de la siguiente forma.
```
bin/
mathapp
pkg/
@@ -139,13 +139,13 @@ Si has seguido todos los pasos anteriores, la estructura de tu directorio se deb
beedb/
beedb.go
util.go
```
Ahora puedes ver la estructura de directorios claramente; `bin` contiene los archivos ejecutables, `pkg` contiene los archivos compliados y `src` los archivos de código fuente del paquete.
(El formato de las variables de entorno en Windows es `%GOPATH%`, sin embargo este libro sigue principalmente el estilo Unix, así que si eres un usuario Windows debes reemplazarlo apropiadamente)
## Links
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección anterior: [Instalación](01.1.md)
- Sección siguiente: [Comandos Go](01.3.md)

View File

@@ -31,7 +31,7 @@ Este comando es para pruebas de compilación. Compilará paquetes dependientes d
## go clean
Este comando es para limpiar los archivos que son generados por los compiladores, incluyendo los siguientes archivos:
```
_obj/ // viejo directorio de object, dejado por Makefiles
_test/ // viejo directorio de test, dejado por Makefiles
_testmain.go // viejo directorio de gotest, dejado por Makefiles
@@ -42,7 +42,7 @@ Este comando es para limpiar los archivos que son generados por los compiladores
DIR(.exe) // generado por go build
DIR.test(.exe) // generado por go test -c
MAINFILE(.exe) // generado por go build MAINFILE.go
```
Usualmente utilizo este comando para limpiar mis archivos antes de subir mi proyecto a Github. Estas son herramientas útiles para pruebas locales, pero inútiles para el control de versiones.
## go fmt
@@ -54,12 +54,12 @@ Usualmente usamos `gofmt -w` en vez de `go fmt`. El último, no rescribirá tus
## go get
Este comando es para obtener paquetes remotos. Hasta el momento soporta BitBucket, Github, Google Code y Launchpad. Actualmente existen dos cosas que suceden después de ejecutar este comando. La primera es que Go descarga el código fuente, luego ejecuta `go install`. Antes de que utilices este comando, asegúrate que tienes instaladas todas las herramientas relacionadas.
```
BitBucket (Mercurial Git)
Github (git)
Google Code (Git, Mercurial, Subversion)
Launchpad (Bazaar)
```
Para poder usar este comando, debes instalar estas herramientas correctamente. No olvides establecer `$PATH`. Por cierto, también soporta nombres de dominios customizados. Usa `go help remote` para más detalles al respecto.
## go install
@@ -69,12 +69,12 @@ Este comando compila todos los paquetes y genera archivos, luego los mueve a `$G
## go test
Este comando carga todos los archivos cuyos nombres incluyen `*_test.go` y genera archivos de pruebas, luego muestra información que se ve de la siguiente forma.
```
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
```
Prueba todos tus archivos de prueba por defecto. Usa el comando `go help testflag` para más detalles.
## go doc
@@ -88,17 +88,17 @@ Ejecuta el comando `godoc -http=:8080`, luego abre `127.0.0.1:8080` en tu navega
## Otros comandos
Go provee comandos adicionales a los que ya mostramos.
```
go fix // actualiza código de una vieja versión antes de go1 a una nueva versión después de go1
go version // muestra información de tu versión de Go
go env // muestra las variables de entorno relacionadas a Go
go list // lista todos los paquetes instalados
go run // compila los archivos temporales y ejecuta la aplicación
```
También hay más detalles de los comandos que hemos hablado, puedes usar el comando `go help <nombre de comando>` para mostrarlos.
## Links
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección anterior: [$GOPATH y el ambiente de trabajo](01.2.md)
- Sección siguiente: [Herramientas de Desarrollo para Go](01.4.md)

View File

@@ -54,14 +54,14 @@ Características de LiteIDE
- Instala gocode
Debes instalar gocode para poder usar el completamiento inteligente
```
go get -u github.com/nsf/gocode
```
- Entorno de compilación
Cambia la configuración en LiteIDE para que se ajuste a tu sistema operativo.
En Windows y usando al versión de 64-bits de Go, debes usar win64 cómo la configuración de entorno en la barra de herramientas. Luego escoge `Options`, busca `LiteEnv` en la lista de la izquierda y abre el archivo `win64.env` en la lista de la derecha.
```
GOROOT=c:\go
GOBIN=
GOARCH=amd64
@@ -70,11 +70,11 @@ Características de LiteIDE
PATH=%GOBIN%;%GOROOT%\bin;%PATH%
。。。
```
Reemplaza `GOROOT=c:\go` con tu ruta de instalación de Go y guarda. Si tienes MinGW64, agrega `c:\MinGW64\bin` a la variable de entorno de tu path para soportar `cgo`.
En Linux y usando la versiónd de 64-bits de Go, debes escoger linux64 como la configuración de entorno en la barra de herramientas. Luego escoge `Options`, busca `LiteEnv` en la lista de la izquierda y abre el archivo `linux64.env` en la lista de la derecha.
```
GOROOT=$HOME/go
GOBIN=
GOARCH=amd64
@@ -83,7 +83,7 @@ Características de LiteIDE
PATH=$GOBIN:$GOROOT/bin:$PATH
。。。
```
Reemplaza `GOROOT=$HOME/go` con tu ruta de instalación de Go y guarda.
- $GOPATH
$GOPATH es la ruta que contiene la lista de proyectos. Abre la herramienta de comandos (o presiona `Ctrl+` en LiteIDE), luego escribe `go help gopath` para más detalles.
@@ -141,22 +141,22 @@ Vim es un editor de texto popular para los programadores, que evolucionó de su
Imagen 1.8 Completamiento inteligente en Vim para Go
1. Realce de sintaxis para Go
```
cp -r $GOROOT/misc/vim/* ~/.vim/
```
2. Habilitando el realce de sintaxis
```
filetype plugin indent on
syntax on
```
3. Instalar [gocode](https://github.com/nsf/gocode/)
```
go get -u github.com/nsf/gocode
```
gocode se instalará por defecto en `$GOBIN`
4. Configura [gocode](https://github.com/nsf/gocode/)
```
~ cd $GOPATH/src/github.com/nsf/gocode/vim
~ ./update.bash
~ gocode set propose-builtins true
@@ -166,7 +166,7 @@ Imagen 1.8 Completamiento inteligente en Vim para Go
~ gocode set
propose-builtins true
lib-path "/home/border/gocode/pkg/linux_amd64"
```
Explicación de la configuración de gocode:
propose-builtins: especifica si abrir o no el completamiento inteligente; falso por defecto.
@@ -183,16 +183,16 @@ Emcas es la llamada arma de Dios. No es solamente un editor, sino un poderoso ID
Imagen 1.10 Panel principal de Emacs editando Go
1. Realce de sintaxis
```
cp $GOROOT/misc/emacs/* ~/.emacs.d/
```
2. Instalar [gocode](https://github.com/nsf/gocode/)
```
go get -u github.com/nsf/gocode
```
gocode se instalará por defecto en `$GOBIN`
3. Configura [gocode](https://github.com/nsf/gocode/)
```
~ cd $GOPATH/src/github.com/nsf/gocode/vim
~ ./update.bash
~ gocode set propose-builtins true
@@ -202,14 +202,14 @@ Imagen 1.10 Panel principal de Emacs editando Go
~ gocode set
propose-builtins true
lib-path "/home/border/gocode/pkg/linux_amd64"
```
4. Instalar [Auto Completion](http://www.emacswiki.org/emacs/AutoComplete)
Descarga y descomprime
```
~ make install DIR=$HOME/.emacs.d/auto-complete
```
Configura el archivo ~/.emacs
```
;;auto-complete
(require 'auto-complete-config)
(add-to-list 'ac-dictionary-directories "~/.emacs.d/auto-complete/ac-dict")
@@ -217,10 +217,10 @@ Imagen 1.10 Panel principal de Emacs editando Go
(local-set-key (kbd "M-/") 'semantic-complete-analyze-inline)
(local-set-key "." 'semantic-complete-self-insert)
(local-set-key ">" 'semantic-complete-self-insert)
```
Visita este [link](http://www.emacswiki.org/emacs/AutoComplete) para más detalles.
5. Configura .emacs
```
;; golang mode
(require 'go-mode-load)
(require 'go-autocomplete)
@@ -305,6 +305,7 @@ Imagen 1.10 Panel principal de Emacs editando Go
(interactive)
(show-all)
(shell-command-on-region (point-min) (point-max) "go tool fix -diff"))
```
6. Felicitaciones, ya estás listo! Speedbar está cerrada por defecto -remueve los símbolos de comentarios en la línea `;;(speedbar 1)` para habilitar esta característica o puedes usarla a través de `M-x speedbar`.
## Eclipse
@@ -327,9 +328,9 @@ Imagen 1.1 Panel principal de Eclipse editando Go
Necesitas instalar git en Windows, usualmente usamos [msysgit](https://code.google.com/p/msysgit/)
Instala gocode en la herramienta de comandos
```
go get -u github.com/nsf/gocode
```
También puedes instalar desde el código fuente si gustas.
4. Descarga e instala [MinGW](http://sourceforge.net/projects/mingw/files/MinGW/)
5. Configura los plugins.
@@ -390,10 +391,10 @@ Las personas que han trabajado con Java deben estar familiarizadas con este IDE.
Introduce la ubicación de tu Go sdk en el siguiente paso - básicamente es tu $GOROOT.
( ***Revisa este [artíclo de blog](http://wuwen.org/tips-about-using-intellij-idea-and-go/) para una configuración paso a paso *** )
(**Revisa este [artíclo de blog](http://wuwen.org/tips-about-using-intellij-idea-and-go/) para una configuración paso a paso** )
## Links
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección anterior: [Comandos Go](01.3.md)
- Sección siguiente: [Resumen](01.5.md)

View File

@@ -4,6 +4,6 @@ En este capítulo hablamos acerca de como instalar Go usando tres métodos difer
## Links
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección anterior: [Herramientas de Desarrollo para Go](01.4.md)
- Siguiente capítulo: [Conocimiento básico de Go](02.0.md)

View File

@@ -98,6 +98,6 @@ Go usa `package` (como lo módulos en Python) para organizar los programas. La f
## Enlaces
- [Directorio](preface.md)
- [Índice](preface.md)
- Sección anterior: [Go, Conocimiento básico](02.0.md)
- Siguiente sección: [Fundamentos de Go](02.2.md)

View File

@@ -47,13 +47,13 @@ Bueno, se que aun no es lo suficientemente sencillo. Vamos a ver como lo mejoram
*/
vname1, vname2, vname3 := v1, v2, v3
```
Ahora se ve mucho mejor. Use `:=` para reemplazar a `var` y `type`, esto se llama declaración breve. Pero espere, esto tiene una limitante, esta forma de declaración solo puede ser utilizada dentro de una función. Si intenta utilizarla fuera del cuerpo de una función va a recibir un error de compilación. Por lo que normalmente utilizamos `var` para definir variables globales, y podemos utilizar la declaración breve en `var()`.
Ahora se ve mucho mejor. Usa `:=` para reemplazar a `var` y `type`, esto se llama declaración breve. Pero espera, esto tiene una limitante, esta forma de declaración solo puede ser utilizada dentro de una función. Si intentas utilizarla fuera del cuerpo de una función vas a recibir un error de compilación. Por lo que normalmente utilizamos `var` para definir variables globales, y podemos utilizar la declaración breve en `var()`.
`_` (guión bajo) es un nombre especial de variable, cualquier valor que le sea otorgado será ignorado. Por ejemplo, le otorgamos `35` a `b`, y descartamos el `34`.( ***Este ejemplo nos muestra como esto funciona. Parece inútil aquí porque normalmente lo utilizamos cuando tomamos los valores de retorno de una función.*** )
```
_, b := 34, 35
```
Si no utilizas alguna de las variables declaradas en el programa, el compilador les lanzara un error. Intente compilar el siguiente código, vea que sucede.
Si no utilizas alguna de las variables declaradas en el programa, el compilador les lanzara un error. Intenta compilar el siguiente código, ve que sucede.
```
package main
@@ -63,7 +63,7 @@ Si no utilizas alguna de las variables declaradas en el programa, el compilador
```
## Constantes
Las llamadas constantes son los valores que se determinan en el momento de compilación, y que no se pueden modificar durante la ejecución. En Go, podemos utilizar números, booleans o string como tipos de constantes.
Las llamadas constantes son los valores que se determinan en el momento de compilación, y que no se pueden modificar durante la ejecución. En Go, podemos utilizar números, booleanos o cadenas como tipos de constantes.
Definimos una constante de la siguiente manera.
```
@@ -95,9 +95,9 @@ En Go, podemos usar `bool` para definir variables de tipo booleanas, su valor pu
```
### Tipos Numéricos
Tipos enteros incluyendo los enteros con signo y sin signo. Para esto Go tiene `int` y `uint` al mismo tiempo, ellos tienen la misma longitud, pero la longitud específica va a depender de su sistema operativo. Ellos utilizan 32-bit en sistemas operativos de 32-bit, y 64-bit en sistemas operativos de 64-bit. Go también tiene tipos que tienen una longitud específica incluyendo `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Tenga en cuenta que `rune` es el alias de `int32` y `byte` es el alias para `uint8`.
Tipos enteros incluyendo los enteros con signo y sin signo. Para esto Go tiene `int` y `uint` al mismo tiempo, ellos tienen la misma longitud, pero la longitud específica va a depender de su sistema operativo. Ellos utilizan 32-bits en sistemas operativos de 32-bits, y 64-bits en sistemas operativos de 64-bits. Go también tiene tipos que tienen una longitud específica incluyendo `rune`, `int8`, `int16`, `int32`, `int64`, `byte`, `uint8`, `uint16`, `uint32`, `uint64`. Tenga en cuenta que `rune` es el alias de `int32` y `byte` es el alias para `uint8`.
Algo importante que debe saber es que no puede asignar valores entre estos tipos, esta operación va a causar un error de compilación.
Algo importante que debes saber es que no puede asignar valores entre estos tipos, esta operación va a causar un error de compilación.
```
var a int8
@@ -107,33 +107,33 @@ Algo importante que debe saber es que no puede asignar valores entre estos tipos
```
Aunque int32 tiene una longitud mayor que uint8, y tiene la misma longitud que int, pero no podrá asignar valores entre ellos. ( ***aquí c afirmará ser de tipo `int`*** )
Los tipos Float tienen `float32` y `float64`, y no tiene tipo llamado `float`, este último solo es el tipo por defecto cuando se utiliza la declaración breve.
Los tipos Float tienen `float32` y `float64`, y no tienen un tipo llamado `float`, este último solo es el tipo por defecto cuando se utiliza la declaración breve.
¿Eso es todo? ¡No! Go también tiene número complejos. `complex128` (con una parte de 64-bit reales y otra parte de 64-bit imaginarios) es el tipo por defecto, si necesita un tipo mas pequeño, hay uno llamado `complex64` (con una parte de 32-bit reales y otra de 32-bit imaginarios). Su forma es `RE+IMi`, donde `RE` es la parte real e `IM` es la parte imaginaria, el último `i` es el número imaginario. Este es un ejemplo de número complejo.
¿Eso es todo? ¡No! Go también tiene número complejos. `complex128` (con una parte de 64-bits reales y otra parte de 64-bits imaginarios) es el tipo por defecto, si necesitas un tipo mas pequeño, hay uno llamado `complex64` (con una parte de 32-bits reales y otra de 32-bits imaginarios). Su forma es `RE+IMi`, donde `RE` es la parte real e `IM` es la parte imaginaria, el último `i` es el número imaginario. Este es un ejemplo de número complejo.
```
var c complex64 = 5+5i
//salida: (5+5i)
fmt.Printf("Value is: %v", c)
```
### String
### Cadenas
Acabamos de hablar sobre que Go utiliza el juego de caracteres de UTF-8. Las Strings son representadas mediante comillas dobles `""` o comillas simples ``` `` ```.
```
// ejemplo de código
var frenchHello string // forma básica de definir una string
var emptyString string = "" // definimos una string con un valor vacío
var frenchHello string // forma básica de definir una cadena
var emptyString string = "" // definimos una cadena con un valor vacío
func test() {
no, yes, maybe := "no", "yes", "maybe" // declaración breve
japaneseHello := "Ohaiou"
frenchHello = "Bonjour" // forma básica para asignar un valor
}
```
Es imposible cambiar el valor de una string por su índice, va a obtener un error cuando compile el siguiente código.
Es imposible cambiar el valor de una cadena por su índice. Vas a obtener un error cuando compiles el siguiente código.
```
var s string = "hello"
s[0] = 'c'
```
Pero, y si ¿realmente deseo cambiar el valor de un solo carácter de una string? Intente utilizar el siguiente código.
Pero, y si ¿realmente deseo cambiar el valor de un solo carácter de una string? Intenta utilizar el siguiente código.
```
s := "hello"
c := []byte(s) // convertimos una string a un tipo []byte
@@ -141,7 +141,7 @@ Pero, y si ¿realmente deseo cambiar el valor de un solo carácter de una string
s2 := string(c) // volvemos a convertirlo a un tipo string
fmt.Printf("%s\n", s2)
```
Podemos utilizar el operador `+` para combinar dos strings.
Podemos utilizar el operador `+` para combinar dos cadenas.
```
s := "hello,"
m := " world"
@@ -151,7 +151,7 @@ Podemos utilizar el operador `+` para combinar dos strings.
y también.
```
s := "hello"
s = "c" + s[1:] // no puede cambiar los valores de una string por índice pero puede obtener sus valores.
s = "c" + s[1:] // no puede cambiar los valores de una cadena por su índices pero puedes obtener sus valores.
fmt.Printf("%s\n", s)
```
Que pasa si ¿quiero tener una string de varias líneas?
@@ -159,7 +159,7 @@ Que pasa si ¿quiero tener una string de varias líneas?
m := `hello
world`
```
capturará todos los caracteres en una string.
` `` ` capturará todos los caracteres en una cadena.
### Tipos de Errores
@@ -172,17 +172,17 @@ Go tiene un tipo de `error` para hacer frente a los mensajes de error. También
```
### Estructura de datos fundamental
La siguiente imagen viene de un artículo sobre [Estructuras de datos en Go](http://research.swtch.com/godata) en [El Blog de Russ Cox](http://research.swtch.com/). Como puede ver, Go nos da bloques de memoria para almacenar datos.
La siguiente imagen viene de un artículo sobre [Estructuras de datos en Go](http://research.swtch.com/godata) en [El Blog de Russ Cox](http://research.swtch.com/). Como puedes ver, Go nos da bloques de memoria para almacenar datos.
![](images/2.2.basic.png?raw=true)
Imagen 2.1 Go estructura de datos fundamental
## Algunas habilidades
## Algunas facilidades
### Definir por grupo
Si desea definir múltiples constantes, variables o importaciones de paquetes, podemos utilizar formularios de grupos.
Si deseas definir múltiples constantes, variables o importaciones de paquetes, podemos utilizar formularios de grupos.
Forma básica.
```
@@ -216,7 +216,7 @@ Forma de grupo.
prefix string
)
```
A menos que asigne el valor de la constante `iota`, el primer valor de la constante en el grupo `const()` va a ser `0`. Si a las siguientes constantes no se les asignan valores explícitamente, sus valores serán el mismo que el último. Si el último valor de la constante es `iota`, los valores de las siguientes constantes que no son asignadas también serán `iota`.
A menos que asignes el valor de la constante `iota`, el primer valor de la constante en el grupo `const()` va a ser `0`. Si a las siguientes constantes no se les asignan valores explícitamente, sus valores serán el mismo que el último. Si el último valor de la constante es `iota`, los valores de las siguientes constantes que no son asignadas también serán `iota`.
### Enumerar con iota
@@ -243,71 +243,71 @@ La razón por la que Go es conciso es porque tiene algunos comportamientos por d
- Cualquier variables que comience con mayúscula se va exportar como pública, de otra manera será una variable privada.
- Se usa la misma regla para funciones y constantes, no existen las palabras reservadas `public` o `private` en Go.
## array, slice, map
## Arreglos, segmentos, mapas
### array
### Arreglos (array)
`array` es un array obviamente, lo definimos de la siguiente forma.
var arr [n]type
en `[n]type`, `n` es la longitud del array, `type` es el tipo de elementos que contiene. Como en otros lenguajes, utilizamos `[]` para obtener o establecer los elementos en el array.
`array` es un arreglo obviamente, lo definimos de la siguiente forma.
```
var arr [10]int // un array de tipo int
arr[0] = 42 // los array arrancan su índice en 0
var arr [n]type
```
en `[n]type`, `n` es la longitud del arreglo, `type` es el tipo de elementos que contiene. Como en otros lenguajes, utilizamos `[]` para obtener o establecer los elementos en el array.
```
var arr [10]int // un arraglo de tipo int
arr[0] = 42 // los arreglos arrancan su índice en 0
arr[1] = 13 // asignamos un valor a un elemento
fmt.Printf("El primer elemento es %d\n", arr[0])
// obtenemos el valor del elemento, este nos devolvera 42
fmt.Printf("El último elemento es %d\n", arr[9])
//este nos devolverá el valor por defecto del elemento número 10 en este array, que es 0 en este caso.
```
Debido a que la longitud es una parte del tipo del array, `[3]int` y `[4]int` son diferentes tipos, por lo que no podemos cambiar la longitud del arrays. Cuando utilizamos arrays como argumentos, las funciones reciben copias en lugar de referencias a ellos! Si lo que busca es utilizar referencias, es posible que desee utilizar `slice` de las que vamos a hablar más adelante.
Debido a que la longitud es una parte del tipo del arreglo, `[3]int` y `[4]int` son diferentes tipos, por lo que no podemos cambiar la longitud del arreglos. Cuando utilizamos arreglos como argumentos, las funciones reciben copias en lugar de referencias a ellos! Si lo que busca es utilizar referencias, es posible que desee utilizar `slice` de las que vamos a hablar más adelante.
Es posible usar `:=` cuando definimos arrays.
```
a := [3]int{1, 2, 3} // define un array de int con 3 elementos
a := [3]int{1, 2, 3} // define un arreglo de int con 3 elementos
b := [10]int{1, 2, 3}
// define array de int con 10 elementos, y los tres primeros son asignados
// define arreglo de int con 10 elementos, y los tres primeros son asignados
// el resto utiliza el valor por defecto 0.
c := [...]int{4, 5, 6} // usamos `` para reemplazar el número de la longitud, Go la va a calcular por usted.
c := [...]int{4, 5, 6} // usamos `` para reemplazar el número de la longitud, Go la va a calcular por ti.
```
Es posible que desee utilizar arrays como elementos de un arrays, vamos a ver como hacerlo.
Es posible que desee utilizar arreglos como elementos de un arreglo, vamos a ver como hacerlo.
```
// definimos un array de dos dimensiones con dos elementos, y cada elemento tiene cuatro elementos.
doubleArray := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
// definimos un arreglo de dos dimensiones con dos elementos, y cada elemento tiene cuatro elementos.
arregloDoble := [2][4]int{[4]int{1, 2, 3, 4}, [4]int{5, 6, 7, 8}}
// podemos escribirlo de una forma más corta.
easyArray := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}
arregloSimple := [2][4]int{{1, 2, 3, 4}, {5, 6, 7, 8}}
```
Array estructuras de datos fundamentales.
Arreglo: estructuras de datos fundamentales.
![](images/2.2.array.png?raw=true)
Imagen 2.2 Relación de mapeo de array multi-dimensionales
Imagen 2.2 Relación de mapeo de arreglo multi-dimensional
### slice
### Segmentos (slice)
En muchas situaciones, un array no es una buena elección. Por ejemplo, nosotros no sabemos cual va a ser el largo del array cuando lo definimos, entonces vamos a necesitar un "array dinámico". Este es llamado `slice` en Go.
En muchas situaciones, un arreglo no es una buena elección. Por ejemplo, nosotros no sabemos cual va a ser el largo del arreglo cuando lo definimos, entonces vamos a necesitar un "arreglo dinámico". Este es llamado `slice` en Go.
Un `slice` no es realmente un `array dinámico`, es un tipo referenciado. `slice` apunta a un `array` subyacente, su declaración es similar a los `array`, pero no necesitan una longitud.
Un `segmento` no es realmente un `arreglo dinámico`, es un tipo referenciado. Un `segmento` apunta a un `arreglo` subyacente, su declaración es similar a los `arreglos`, pero no necesitan una longitud.
```
// al igual que como definimos un array, pero no le pasamos la longitud esta vez
var fslice []int
// al igual que como definimos un arreglo, pero no le pasamos la longitud esta vez
var fsegmento []int
```
Entonces definimos un `slice`, e inicializamos sus datos.
Entonces definimos un `segmento`, e inicializamos sus datos.
```
slice := []byte {'a', 'b', 'c', 'd'}
segmento := []byte {'a', 'b', 'c', 'd'}
```
Un `slice` puede ser re-definido desde otro slice o array existente. Un `slice` usa `array[i:j]` para tomar sus valores, donde `i` es
el comienzo del indice y `j` es el final del indice, note que `array[j]` no será un, ahora la longitud
del slice es `j-i`.
Un `segmento` puede ser re-definido desde otro slice o array existente. Un `segmento` usa `arreglo[i:j]` para tomar sus valores, donde `i` es
el índice del comienzo y `j` es el índice del final, note que `arreglo[j]` no será segmentado, porque la longitud
del segmento es `j-i`.
```
// definimos un slice con 10 elementos donde el tipo es byte
// definimos un segmento con 10 elementos donde el tipo es byte
var ar = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// definimos dos slices de tipo []byte
// definimos dos segmento de tipo []byte
var a, b []byte
// a apunta a los elementos del tercero al quinto elemento en el array ar.
@@ -318,26 +318,26 @@ del slice es `j-i`.
b = ar[3:5]
// ahora b tiene los elementos ar[3] y ar[4]
```
Note la diferencia entre `slice` y `array` cuando los definimos. Nosotros usamos `[…]` para que Go
calcule la longitud pero usamos`[]` para definir unicamente slice.
Note la diferencia entre `segmento` y `arreglo` cuando los definimos. Nosotros usamos `[…]` para que Go
calcule la longitud pero usamos`[]` para definir unicamente un segmento.
Su estructura de datos subyacente.
La estructura de datos subyacente a un segmento.
![](images/2.2.slice.png?raw=true)
Imagen 2.3 Similitud entre slice y array
slice tiene algunas operaciones utiles.
Los segmentos tienen algunas operaciones utiles.
- `slice` comienza en 0, `ar[:n]` es igual a `ar[0:n]`
- El segundo indice sera la longitud del `slice` si lo omitimos, `ar[n:]` será igual a `ar[n:len(ar)]`.
- Se puede usar `ar[:]` para tomar todo el array, la razón de esto se explica en las dos anteriores explicaciones.
- Un `segmento` comienza en 0, `ar[:n]` es igual a `ar[0:n]`
- El segundo índice sera la longitud del `slice` si lo omitimos, `ar[n:]` será igual a `ar[n:len(ar)]`.
- Se puede usar `ar[:]` para tomar todo el arreglo, la razón de esto se explica en las dos anteriores explicaciones.
Más ejemplos acerca de `slice`
Más ejemplos acerca de `segmentos`
```
// definimos un array
// definimos un arreglo
var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
// definimos dos slices
// definimos dos segmentos
var aSlice, bSlice []byte
// Algunas operaciones útiles
@@ -345,21 +345,21 @@ Más ejemplos acerca de `slice`
aSlice = array[5:] // es igual a aSlice = array[5:10] aSlice tiene los elementos f,g,h,i,j
aSlice = array[:] // es igual a aSlice = array[0:10] aSlice tiene todos los elementos
// slice desde slice
// segmento desde segmento
aSlice = array[3:7] // aSlice tiene los elementos d,e,f,glen=4cap=7
bSlice = aSlice[1:3] // bSlice contiene aSlice[1], aSlice[2], entonces este tendrá los elementos e,f
bSlice = aSlice[:3] // bSlice contiene aSlice[0], aSlice[1], aSlice[2], entonces este tiene d,e,f
bSlice = aSlice[0:5] // bSlice se puede expandir, ahora bSlice contiene d,e,f,g,h
bSlice = aSlice[:] // bSlice tiene los mismos elementos que aSlice, que son d,e,f,g
```
`slice` es un tipo de referencia, por lo que si uno se modifica entonces afectará al resto.
Un `segmento` es un tipo de referencia, por lo que si uno se modifica entonces afectará al resto.
Por ejemplo, con los elementos de anteriores `aSlice` y `bSlice`, si se modifica el valor de algún elemento en `aSlice`,
`bSlice` será modificado también.
`slice` por definición es como una estructura, este contiene tres partes.
`slice` por definición es como una estructura, y contiene tres partes.
- Un puntero que apunta donde comienza el `slice`.
- la longitud del `slice`.
- Un puntero que apunta donde comienza el `segmento`.
- la longitud del `segmento`.
- Capacidad, la longitud de donde comienza el indice hacia donde termina el indice del `slice`.
```
Array_a := [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
@@ -371,28 +371,28 @@ Los fundamentos de la estructura de datos del código anterior es el siguiente.
Imagen 2.4 Array información del slice
Hay algunas funciones integradas para las slice.
Hay algunas funciones integradas para los segmentos.
- `len` nos devuelve la longitud del `slice`.
- `cap` nos devuelve la longitud máxima del `slice`
- `append` añade uno o mas elementos al `slice`, y nos devuelve el `slice` .
- `copy` copia elementos de un slice hacia otro, y nos devuelve el número de elementos que fueron copiados.
- `len` nos devuelve la longitud del `segmento`.
- `cap` nos devuelve la longitud máxima del `segmento`
- `append` añade uno o mas elementos al `segmento`, y nos devuelve el `segmento` .
- `copy` copia elementos de un segmento hacia otro, y nos devuelve el número de elementos que fueron copiados.
Atención: `append` va a cambiar el array al que apunta el `slice`, y afectará a los otros que apuntan al mismo array.
Ademas si no tiene una longitud suficiente para el slice (`(cap-len) == 0`), `append` nos va a devolver un nuevo array para este slice, en este punto,
los otros slices van a apuntan al anterior array nos serán afectados.
### map
### Mapas (map)
`map` es como un diccionario en Python, lo usamos de la siguiente forma `map[claveTipo]tipoValor` para definirlo.
Un `mapa` es como un diccionario en Python, lo usamos de la siguiente forma `mapa[claveTipo]tipoValor` para definirlo.
Vamos a ver algo de código, para configurar o tomar un valor de un `map` es como en un `slice`, usamos la `key` para ello, pero el indice en un `slice` puede ser
solo de tipo int, y en un `map` podemos usar mucho mas que eso, `int`, `string`, o lo que quieras. Ademas, todos ellos
Vamos a ver algo de código, para configurar o tomar un valor de un `mapa` es como en un `segmento`, usamos la `llave` para ello, pero el indice en un `segmento` puede ser
solo de tipo entero, y en un `mapa` podemos usar mucho mas que eso, `entero`, `cadena`, o lo que quieras. Ademas, todos ellos
pueden utilizar `==` y `!=` para comparar valores.
```
// usamos string tipo de clave (key), int como el tipo de valor, y debemos usar `make` para inicializarlo.
// usamos string tipo de llave (key), int como el tipo de valor, y debemos usar `make` para inicializarlo.
var numbers map[string] int
// otra forma de definir un map
// otra forma de definir un mapa
numbers := make(map[string]int)
numbers["one"] = 1 // asignamos el valor para la clave
numbers["ten"] = 10
@@ -403,16 +403,16 @@ pueden utilizar `==` y `!=` para comparar valores.
```
Algunas cosas a tener en cuenta cuando usamos map.
- `map` esta y es desordenado, cada vez que imprimamos `map` vamos a obtener diferentes resultados. Es imposible obtener un valor por índice, debe usar la clave.
- `map` no tiene una longitud fija, es un tipo de referencia al igual que los `slice`.
- `len` también funciona en `map`, este devuelve el número de claves que tiene el map.
- Es muy sencillo modificar el valor de un elemento del `map`, simplemente usamos `numbers["one"]=11` para cambiar el valor que contiene la clave one a `11`.
- Un `mapa` está y es desordenado, cada vez que imprimamos un `mapa` vamos a obtener diferentes resultados. Es imposible obtener un valor por índice, debe usar la clave.
- Un `mapa` no tiene una longitud fija, es un tipo de referencia al igual que los `segmentos`.
- `len` también funciona con `mapas`, este devuelve el número de claves que tiene el map.
- Es muy sencillo modificar el valor de un elemento del `mapa`, simplemente usamos `numbers["one"]=11` para cambiar el valor que contiene la clave one a `11`.
Se puede usar la forma `clave:valor` para inicializar los valores del map, y `map` tiene internamente los métodos para verificar si la clave existe.
Utilice `delete` para borrar un elemento del `map`.
Utilice `delete` para borrar un elemento del `mapa`.
```
// Inicialice un map
// Inicialice un mapa
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
// map nos devuelve dos valores. El segundo valor ok es false si la clave no
//existe true de otra forma.
@@ -435,7 +435,7 @@ cualquier cambio van a afectar a ambos.
```
### make, new
`make` realiza la asignación de memoria para construir las estructuras como los `map`, `slice`, o `channel`, `new`
`make` realiza la asignación de memoria para construir las estructuras como los `mapas`, `segmentos`, o `canales`, `new`
es para la reserva de memoria de cada tipo.
`new(T)` reservamos la memoria para el valor vacío del tipo `T`'s, devuelve la dirección de memoria, que es el valor del tipo `*T`. En los términos de Go,
@@ -443,11 +443,11 @@ este devuelve un puntero, que apunta al valor vacío del tipo `T`.
`new` devuelve punteros.
La función incorporada `make(T, args)` tiene un diferente efecto que `new(T)`, `make` puede ser usado para `slice`, `map`,
y `channel`, y nos devuelve un valor inicializado con valor inicial del tipo `T`. La razón para hacer esto es porque estos tres tipos
por debajo deben ser inicializados antes que los punteros a ellos. Por ejemplo, un `slice` contiene punteros que por debajo apuntan a
un `array`, longitud y capacidad. Antes de que esta información sea inicializada, un `slice` es `nil`, entonces para un `slice`, `map`,
`channel`, `make` inicializa los datos que tienen por debajo, y asigna algunos valores configurables.
La función incorporada `make(T, args)` tiene un diferente efecto que `new(T)`, `make` puede ser usado para `segmentos`, `mapas`,
y `canales`, y nos devuelve un valor inicializado con valor inicial del tipo `T`. La razón para hacer esto es porque estos tres tipos
por debajo deben ser inicializados antes que los punteros a ellos. Por ejemplo, un `segmento` contiene punteros que por debajo apuntan a
un `arreglo`, longitud y capacidad. Antes de que esta información sea inicializada, un `segmento` es `nil`, entonces para un `segmento`, `mapa`y
`canal`, `make` inicializa los datos que tienen por debajo, y asigna algunos valores configurables.
`make` devuelve valores distinto de cero.

View File

@@ -30,7 +30,7 @@ Lo más útil de `if` en Go es que puede tener una instrucción de inicializaci
// el siguiente código no va a compilar
fmt.Println(x)
```
Utilice if-else para múltiples condiciones.
Utiliza if-else para múltiples condiciones.
```
if entero == 3 {
fmt.Println("entero es igual a 3")
@@ -42,7 +42,7 @@ Utilice if-else para múltiples condiciones.
```
### goto
Go la palabra reservada `goto`, sea cuidadoso cuando la usa. `goto` tiene un salto hacia el `label` hacia el cuerpo de el mismo bloque de código.
Go la palabra reservada `goto`, se cuidadoso cuando la usas. `goto` tiene un salto hacia la `etiqueta` en el cuerpo de el mismo bloque de código.
```
func myFunc() {
i := 0
@@ -52,11 +52,11 @@ Go la palabra reservada `goto`, sea cuidadoso cuando la usa. `goto` tiene un sal
goto Here // salta hacia el label "Here"
}
```
El nombre del label diferencia entre mayúsculas y minúsculas.
El nombre de la etiqueta diferencia entre mayúsculas y minúsculas.
### for
`for` es la lógica de control mas poderosa en Go, puede leer los datos en los bucles y realizar operaciones iterativas, al igual que un típico `while`.
`for` es la lógica de control mas poderosa en Go, puede leer los datos en los ciclos y realizar operaciones iterativas, al igual que un típico `while`.
```
for expression1; expression2; expression3 {
//...
@@ -87,14 +87,14 @@ Si no son necesarios, podemos omitir a `expression1` y `expression3`.
sum += sum
}
```
Podemos omitir también el `;`. Se siente familiar? Si, es un `while`.
Podemos omitir también el `;`. ¿Se siente familiar? Si, es un `while`.
```
sum := 1
for sum < 1000 {
sum += sum
}
```
Hay dos operaciones importantes en los bucles que son `break` y `continue`. `break` salta afuera del bucle, y `continue` salta el bucle actual y continua en el siguiente. Si usted anida bucles, utilice `break` para saltar al bucle que esta junto.
Hay dos operaciones importantes en los ciclos que son `break` y `continue`. `break` salta afuera del ciclo, y `continue` salta el ciclo actual y continua en el siguiente. Si usted anida ciclos, utilice `break` para saltar al bucle que esta junto.
```
for index := 10; index>0; index-- {
if index == 5{
@@ -105,22 +105,22 @@ Hay dos operaciones importantes en los bucles que son `break` y `continue`. `bre
// break imprime 10、9、8、7、6
// continue imprime 10、9、8、7、6、4、3、2、1
`for` podría leer los datos desde un `slice` o un `map` cuando es utilizado con `range`.
`for` podría leer los datos desde un `segmento` o un `mapa` cuando es utilizado con `range`.
for k,v:=range map {
fmt.Println("map's key:",k)
fmt.Println("map's val:",v)
fmt.Println("llave del mapa:",k)
fmt.Println("valor del mapa:",v)
}
```
Como Go soporta el retorno de valores múltiples y nos da errores de compilación cuando utiliza valores que no fueron definidos, por eso puede necesitar utilizar `_` para descartar algunos valores de retorno.
```
for _, v := range map{
fmt.Println("map's val:", v)
fmt.Println("valor del mapa:", v)
}
```
### switch
A veces puede pensar que esta utilizando demasiados valores `if-else` para implementar alguna lógica, también puede pensar que no se ve bien y que no sea correcto para mantener a futuro. Ahora es tiempo para utilizar `switch` para resolver este problema.
A veces puedes pensar que estas utilizando demasiados valores `if-else` para implementar alguna lógica, también puedes pensar que no se ve bien y que no sea correcto para mantener a futuro. Ahora es tiempo para utilizar `switch` para resolver este problema.
```
switch sExpr {
case expr1:
@@ -192,7 +192,7 @@ Podemos obtener la siguiente información del ejemplo anterior.
- Utilizamos la palabra reservada `func` para definir la función llamada `funcName`.
- Funciones tienen cero, uno o mas de un argumento, el tipo del argumento después del nombre del mismo y separados por `,`.
- Las funciones pueden devolver múltiples valores.
- Tiene dos valores de retorno llamados `output1` y `output2`, se pueden omitir los nombre y utilizar unicamente los tipos.
- El ejemplo iene dos valores de retorno llamados `output1` y `output2`, se pueden omitir los nombre y utilizar unicamente los tipos.
- Si solo hay un valor de retorno y omite el nombre, no va a necesitar comas para retornar mas valores.
- Si la función no tiene valores de retorno, puede omitir la parte de retorno.
- Si la función tiene valores de retorno, va a necesitar utilizar `return` en alguna parte del cuerpo de la función.
@@ -249,7 +249,7 @@ Vamos a utilizar el ejemplo anterior aquí.
fmt.Printf("%d * %d = %d\n", x, y, xTIMESy)
}
```
En el ejemplo anterior devolvemos dos valores sin nombre, y usted también puede nombrarlos. Si nombramos los valores de retornos, solo vamos a utilizar `return` para devolver para devolver bien los valores ya que se inicializan en la función automáticamente. Debe tener en cuenta que si sus funciones se van a utilizar fuera del paquete, lo que significa que los nombre de las funciones inician con mayúsculas, es mejor que escriba la sentencia mas completa para `return`; esto hace que es código sea mas legible.
En el ejemplo anterior devolvemos dos valores sin nombre, y tu también puedes nombrarlos. Si nombramos los valores de retorno, solo vamos a utilizar `return` para devolver para devolver bien los valores ya que se inicializan en la función automáticamente. Debes tener en cuenta que si tus funciones se van a utilizar fuera del paquete, lo que significa que los nombre de las funciones inician con mayúsculas, es mejor que escriba la sentencia mas completa para `return`; esto hace que es código sea mas legible.
```
func SumAndProduct(A, B int) (add int, Multiplied int) {
add = A+B
@@ -263,7 +263,7 @@ Go soporta funciones con un número variable de argumentos. Estas funciones son
```
func myfunc(arg ...int) {}
```
`arg …int` le dice a Go que esta función tiene argumentos variables. Tenga en cuenta que estos argumentos son de tipo `int`. En el cuerpo de la función , `arg` será un `slice` de `int`.
`arg …int` le dice a Go que esta función tiene argumentos variables. Ten en cuenta que estos argumentos son de tipo `int`. En el cuerpo de la función , `arg` será un `segmento` de `enteros`.
```
for _, n := range arg {
fmt.Printf("Y el número es: %d\n", n)
@@ -295,7 +295,7 @@ Vamos a ver un ejemplo para probar lo que decimos.
fmt.Println("x = ", x) // debe imprimir "x = 3"
}
```
¿Usted vio eso? Siempre que llamamos a `add1`, y `add1` le suma uno a `a`, el valor de `x` no sufre cambios.
¿Viste eso? Siempre que llamamos a `add1`, y `add1` le suma uno a `a`, el valor de `x` no sufre cambios.
El motivo de esto es muy sencillo: cuando llamamos a `add1`, nosotros obtenemos una copia de `x` para esto, no `x` en si mismo.
@@ -323,15 +323,15 @@ Para eso necesitamos utilizar punteros. Sabemos que las variables son almacenada
fmt.Println("x = ", x) // debe imprimir "x = 4"
}
```
Ahora podemos cambiar el valor de `x` en la función. Porque usamos punteros? Cual es la ventaja?
Ahora podemos cambiar el valor de `x` en la función. ¿Por qué usamos punteros? ¿Cuál es la ventaja?
- Usamos mas funciones que modifiquen una misma variable.
- Tiene un bajo costo utilizar direcciones de memoria (8 bytes), la copia no es una forma eficiente tanto en el tiempo como en el espacio para pasar variables.
- `string`, `slice`, `map` son tipos de referenciados, por eso ellos por defecto utilizan punteros cuando se pasan a funciones. (Atención: si necesitas cambiar el tamaño de un `slice`, vas a necesitar pasar el puntero de forma explicita)
- Las `cadenas`, `segmentos` y `mapas` son tipos de referenciados, por eso ellos por defecto utilizan punteros cuando se pasan a funciones. (Atención: si necesitas cambiar el tamaño de un `segmento`, vas a necesitar pasar el puntero de forma explicita)
### defer
Go tiene un muy buen diseño llamado `defer`, uno puede tener muchas declaraciones de `defer` en una función; ellos se ejecutan en orden inverso cuando el programa ejecuta el final de la función. Especialmente cuando el programa abre un recurso como un archivo, estos archivos tienen que ser cerrados antes de que la función devuelva un error. Vamos a ver algún ejemplo.
Go tiene una palabra reservada muy bien diseñada llamada `defer`, puedes tener muchas declaraciones de `defer` en una función; ellas se ejecutan en orden inverso cuando el programa ejecuta el final de la función. Es útil especialmente cuando el programa abre un recurso como un archivo, estos archivos tienen que ser cerrados antes de que la función devuelva un error. Vamos a ver algún ejemplo.
```
func ReadWrite() bool {
file.Open("file")
@@ -376,7 +376,7 @@ Las funciones son también variables en Go, podemos usar un `type` para definirl
```
type typeName func(input1 inputType1 , input2 inputType2 [, ...]) (result1 resultType1 [, ...])
```
Cual es la ventaja de esta característica? Entonces podemos pasar funciones como valores.
¿Cuál es la ventaja de esta característica? La respuesta es que podemos pasar funciones como valores.
```
package main
import "fmt"
@@ -418,7 +418,7 @@ Cual es la ventaja de esta característica? Entonces podemos pasar funciones com
fmt.Println("Even elements of slice are: ", even)
}
```
Es muy útil cuando usamos interfaces. Como puede ver `testInt` es una variable que tiene como tipo una función, y devuelve valores y el argumento de `filter` es el mismo que el de `testInt`. Por lo tanto, tenemos una lógica mas compleja en nuestro programa, y hacemos nuestro código mas flexible.
Es muy útil cuando usamos interfaces. Como puedes ver `testInt` es una variable que tiene como tipo una función, y devuelve valores y el argumento de `filter` es el mismo que el de `testInt`. Por lo tanto, tenemos una lógica mas compleja en nuestro programa, y hacemos nuestro código mas flexible.
### Panic y Recover
@@ -511,6 +511,6 @@ Tenemos algunos operadores especiales para importar paquetes, y los principiante
## Enlaces
- [Indice](preface.md)
- [Índice](preface.md)
- Sección anterior: [Principios de Go](02.2.md)
- Siguiente sección: [struct](02.4.md)

View File

@@ -209,6 +209,6 @@ Go utiliza una forma muy sencilla para resolverlo. Los campos exteriores consigu
```
## Enlaces
- [Indice](preface.md)
- [Índice](preface.md)
- Sección anterior: [Sentencias de control y funciones](02.3.md)
- Siguiente sección: [Orientado a objetos](02.5.md)

View File

@@ -4,7 +4,7 @@ En las ultimas dos secciones hablamos de funciones y struct, alguna vez pensaste
## Métodos
Supongamos que definimos un struct del estilo rectángulo(rectangle), y usted busca calcular el área, por lo general vamos a usar el siguiente código para lograr este objetivo.
Supongamos que definimos un struct del estilo rectángulo(rectangle), y buscas calcular el área, por lo general vamos a usar el siguiente código para lograr este objetivo.
```
package main
import "fmt"
@@ -36,7 +36,7 @@ Obviamente, no es “cool”. Además el área debería ser propiedad del circul
Por estas razones, tenemos conceptos sobre `métodos`. `métodos` es afiliado a un tipo, tienen la misma sintaxis que una función excepto por una palabra más después de la palabra reservada `func` que es llamada receptor (`receiver`) que es el cuerpo principal de ese método.
Utilice el mismo ejemplo, `Rectangle.area()` pertenece al rectángulo, no como una función periférica. Mas específicamente, `length`, `width` y `area()` todos pertenecen a rectángulo.
Utiliza el mismo ejemplo, `Rectangle.area()` pertenece al rectángulo, no como una función periférica. Mas específicamente, `length`, `width` y `area()` todos pertenecen a rectángulo.
Como dice Rob Pike.
@@ -45,7 +45,7 @@ Como dice Rob Pike.
Sintaxis de un método.
```
func (r ReceiverType) funcName(parameters) (results)
```
```
Cambiemos el ejemplo anterior para utilizar métodos.
```
package main
@@ -121,7 +121,7 @@ Espero que ahora sepa como utilizar los tipos personalizados. Es similar a `type
Volvamos a los `métodos`.
Puede utilizar tantos métodos en tipos personalizados como desees.
Puedes utilizar tantos métodos en tipos personalizados como desees.
```
package main
import "fmt"
@@ -210,17 +210,17 @@ Entonces vamos a definir algunos métodos para personalizar nuestros tipos.
- PaintItBlack() configuramos el color para todas las Box en BoxList a negro.
- String() usamos Color como su receptor, devolvemos un string con formato de el nombre del color.
Es mucho mas claro cuando usamos palabras para describir nuestro requerimientos? Usualmente escribimos nuestros requerimientos antes de comenzar a programar.
¿Es mucho mas claro cuando usamos palabras para describir nuestro requerimientos? Usualmente escribimos nuestros requerimientos antes de comenzar a programar.
### Utilizar punteros como un receptor
Vamos a mirar el método `SetColor`, su receptor es un puntero de tipo Box. Si, podes usar `*Box` como receptor. Porque usaríamos un puntero a? Porque buscamos cambiar el color de Box en este método, si no usamos un puntero, solo cambiaría el valor de la copia de Box.
Vamos a mirar el método `SetColor`, su receptor es un puntero de tipo Box. Si, puedes usar `*Box` como receptor. ¿Por qué usaríamos un puntero aquí? Porque buscamos cambiar el color de Box en este método, si no usamos un puntero, solo cambiaría el valor de la copia de Box.
Si vemos el receptor como el primer argumento de los métodos, no es difícil de entender como funcionan estos.
Podría decir que deberíamos usar `*b.Color=c` en vez de `b.Color=c` en el método SetColor(). Cualquiera de los dos estaría bien, porque Go lo sabe interpretar. ¿Ahora crees que Go es mas fascinante?
También podría decir que deberíamos usar `(&bl[i]).SetColor(BLACK)` en `PaintItBlack` porque le pasamos un puntero a `SetColor`. Una vez más, cualquiera de los dos esta bien, porque Go sabe interpretarlo correctamente!
También podría decir que deberíamos usar `(&bl[i]).SetColor(BLACK)` en `PaintItBlack` porque le pasamos un puntero a `SetColor`. Una vez más, cualquiera de los dos esta bien, porque ¡Go sabe interpretarlo correctamente!
### Herencia de métodos
@@ -298,10 +298,10 @@ Si queremos que Employee tenga su propio método llamado `SayHi`, podemos defini
sam.SayHi()
}
```
Ahora usted es capaz de escribir programas que utilicen el paradigma Orientado a Objetos, los métodos utilizan la regla de que los que tienen nombre que se inician con mayúsculas van a ser públicos o privados en caso contrario.
Ahora eres capaz de escribir programas que utilicen el paradigma Orientado a Objetos, los métodos utilizan la regla de que los que tienen nombre que se inician con mayúsculas van a ser públicos o privados en caso contrario.
## Enlaces
- [Indice](preface.md)
- [Índice](preface.md)
- Sección anterior: [struct](02.4.md)
- Siguiente sección: [interfaces](02.6.md)

View File

@@ -187,7 +187,7 @@ Si una función usa una interfaz vacía como su tipo de argumento, esta puede ac
Cualquier variable puede usarse en una interfaz, entonces podemos pensar sobre como podemos usar esta característica para pasar cualquier tipo de variable a una función.
Por ejemplo, usamos mucho fmt.Println, pero alguna vez notaste que este acepta cualquier tipo de argumento? Si vemos el código fuente de fmt que es libre, podemos ver la siguiente definición.
Por ejemplo, usamos mucho fmt.Println, pero alguna vez notaste que ¿acepta cualquier tipo de argumento? Si vemos el código fuente de fmt que es libre, podemos ver la siguiente definición.
```
type Stringer interface {
String() string
@@ -224,13 +224,13 @@ Volviendo atrás al ejemplo de Box, podemos ver que Color también implementa la
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
fmt.Println("The biggest one is", boxes.BiggestsColor())
```
Atención: Si el tipo implementa la interfaz `error`, fmt va a llamar a `error()`, entonces en este punto usted no tendrá que implementar Stringer.
Atención: Si el tipo implementa la interfaz `error`, fmt va a llamar a `error()`, entonces en este punto no tendrás que implementar Stringer.
### Tipos de variables en un interfaz
Si una variable es del tipo que implementa una interfaz, sabemos que cualquier otro tipo que implemente la misma interfaz puede ser asignada a esta variable. La pregunta es ¿Como podemos saber cual es el tipo específico almacenado en la interfaz? Tenemos dos formas, que le voy a comentar a continuación.
Si una variable es del tipo que implementa una interfaz, sabemos que cualquier otro tipo que implemente la misma interfaz puede ser asignada a esta variable. La pregunta es ¿Cómo podemos saber cual es el tipo específico almacenado en la interfaz? Tenemos dos formas, que te voy a comentar a continuación.
- Patrón de afirmación Comma-ok
- Patron de Aserción Comma-ok
Go tiene la sintaxis `value, ok := element.(T)`. Esto comprueba si la variable es del tipo que se espero, donde value es el valor de la variable, y ok es un valor de tipo booleano, element es la variable interfaz y T es el tipo que se afirma tener.
@@ -326,7 +326,7 @@ Una cosa que deberíamos recordar es que `element.(type)` no puede ser usado fue
### Interfaces embebidas
La como más atractiva es que Go tiene mucha sintaxis para la lógica embebida, como campos anónimos en un struct. No es para sorprenderse, que podamos usar interfaces también como campos anónimos, pero vamos a llamarlas `Interfaces embebidas`. Aquí, vamos a seguir las mismas reglas que para los campos anónimos. Más específicamente, si una interfaz tiene otra interfaz como una interfaz embebida, esta tendrá todos los métodos que la clase embebida tiene.
La cosa más atractiva es que Go tiene mucha lógica embebida en su sintaxis, como campos anónimos en un struct. No es para sorprenderse, que podamos usar interfaces también como campos anónimos, pero vamos a llamarlas `Interfaces embebidas`. Aquí, vamos a seguir las mismas reglas que para los campos anónimos. Más específicamente, si una interfaz tiene otra interfaz como una interfaz embebida, esta tendrá todos los métodos que la clase embebida tiene.
Podemos ver el archivo fuente `container/heap` que tiene una definición como la siguiente.
```
@@ -335,9 +335,9 @@ Podemos ver el archivo fuente `container/heap` que tiene una definición como la
Push(x interface{}) //el método Push para empujar elementos a la pila
Pop() interface{} //el elemento Pop que saca elementos de la pila
}
```
Podemos ver que `sort.Interface` es una interfaz embebida, por lo que la interfaz anterior tiene tres métodos que son explícitos de `sort.Interface`.
```
type Interface interface {
// Len es el número de elementos en la colección.
Len() int
@@ -347,9 +347,9 @@ Podemos ver que `sort.Interface` es una interfaz embebida, por lo que la interfa
// Swap intercambia los elementos con índices i y j.
Swap(i, j int)
}
```
Otro ejemplo es el de `io.ReadWriter` en el paquete `io`.
```
// io.ReadWriter
type ReadWriter interface {
Reader
@@ -373,7 +373,7 @@ Después de eso, necesitamos convertir el tipo reflect de el valor que tomamos a
fmt.Println("kind is float64:", v.Kind() == reflect.Float64)
fmt.Println("value:", v.Float())
```
Finalmente, si buscamos cambiar el valor que vino del tipo reflects,necesitamos hacerlo modificable. Como hablamos antes, esta es una diferencia entre pasar por valor o por referencia. El siguiente código no compilará.
Finalmente, si buscamos cambiar el valor que vino del tipo reflects, necesitamos hacerlo modificable. Como hablamos antes, esta es una diferencia entre pasar por valor o por referencia. El siguiente código no compilará.
```
var x float64 = 3.4
v := reflect.ValueOf(x)
@@ -386,10 +386,10 @@ En lugar de eso, debemos usar el siguiente código para cambiar el valor de los
v := p.Elem()
v.SetFloat(7.1)
```
Acabo de hablar sobre los conocimientos básicos de sobre el uso de reflexión (reflection), debería practicar más para entenderlo mejor.
Acabamos de hablar sobre los conocimientos básicos de sobre el uso de reflexión (reflection), deberías practicar más para entenderlo mejor.
## Enlaces
- [Indice](preface.md)
- [Índice](preface.md)
- Sección anterior: [Orientado a objetos](02.5.md)
- Siguiente sección: [Concurrencia](02.7.md)

View File

@@ -51,7 +51,7 @@ El manejador de tareas solo usa un hilo para correr todas la goroutines, lo que
## Canales
goroutines son ejecutadas en el mismo espacio de direcciones de memoria, por lo que se tiene que mantener sincronizadas si buscas acceder a la memoria compartida. ¿Como nos comunicamos entre diferentes goroutines? Go utiliza un muy buen mecanismo de comunicación llamado `canales`(channel). Los `canales` son como dos tuberías (o pipes) en la shell de Unix: usando canales para enviar o recibir los datos. El unico tipo de datos que se puede usar en los canales es el tipo `channel` y la palabra reservada para eso es `chan`. Tenga en cuenta que para crear un nuevo `channel` debemos usar la palabra reservada `make`.
goroutines son ejecutadas en el mismo espacio de direcciones de memoria, por lo que se tiene que mantener sincronizadas si buscas acceder a la memoria compartida. ¿Cómo nos comunicamos entre diferentes goroutines? Go utiliza un muy buen mecanismo de comunicación llamado `canales`(channel). Los `canales` son como dos tuberías (o pipes) en la shell de Unix: usando canales para enviar o recibir los datos. El unico tipo de datos que se puede usar en los canales es el tipo `channel` y la palabra reservada para eso es `chan`. Ten en cuenta que para crear un nuevo `channel` debemos usar la palabra reservada `make`.
```
ci := make(chan int)
cs := make(chan string)
@@ -91,7 +91,7 @@ Enviando y recibimos los datos por defecto en bloques, por lo que es mucho mas f
## Buffered channels
Anteriormente hice una introducción sobre canales non-buffered channels (non-buffered channels), y Go también tiene 'buffered channels' que pueden guardar mas de un elemento. Por ejemplo, `ch := make(chan bool, 4)`, aca creamos un canal que puede guardar 4 elementos booleanos. Por lo tanto con este canal, somos capaces de enviar 4 elementos sin el bloqueo, pero la goroutine se bloqueará cuando intente enviar un quito elemento y la goroutine no lo recibirá.
Anteriormente hice una introducción sobre canales non-buffered channels (non-buffered channels), y Go también tiene 'buffered channels' que pueden guardar mas de un elemento. Por ejemplo, `ch := make(chan bool, 4)`, aquí creamos un canal que puede guardar 4 elementos booleanos. Por lo tanto con este canal, somos capaces de enviar 4 elementos sin el bloqueo, pero la goroutine se bloqueará cuando intente enviar un quinto elemento y la goroutine no lo recibirá.
```
ch := make(chan type, n)
@@ -147,7 +147,7 @@ Otra cosa que deber tener que recordar es que los canales son diferentes a los a
## Select
En los ejemplos anteriores, nosotros usamos solo un canal, pero ¿como podemos lidiar con mas de un canal? Go tiene la palabra reservada llamada `select` para escuchar muchos canales.
En los ejemplos anteriores, nosotros usamos solo un canal, pero ¿cómo podemos lidiar con más de un canal? Go tiene la palabra reservada llamada `select` para escuchar muchos canales.
`select` de forma predeterminada es bloqueante, y este continua la ejecución solo cuando un canal tiene datos o recibió datos. Si varios canales están listos para usarse al mismo tiempo, select elegirá cual ejecutar al azar.
```
@@ -179,9 +179,9 @@ En los ejemplos anteriores, nosotros usamos solo un canal, pero ¿como podemos l
}()
fibonacci(c, quit)
}
```
`select` también tiene `default`, al igual que el `switch`. Cuando todos los canales no están listos para ser usados, ejecuta el default (no espera mas por el canal).
```
select {
case i := <-c:
// usa i
@@ -237,6 +237,6 @@ El paquete `runtime` tiene algunas funciones para hacer frente a las goroutines.
## Enlaces
- [Indice](preface.md)
- [Índice](preface.md)
- Sección anterior: [interfaces](02.6.md)
- Siguiente sección: [Resumen](02.8.md)

View File

@@ -27,6 +27,6 @@ Si entendes como usar estas 25 palabras reservadas, usted ya a aprendido mucho s
## Enlaces
- [Indices](preface.md)
- [Índice](preface.md)
- Sección anterior: [Concurrencia](02.7.md)
- Siguiente sección: [Conocimientos básicos sobre la Web](03.0.md)