Correccion de algunos errores

This commit is contained in:
Aldo Méndez
2017-04-14 17:08:56 -05:00
committed by GitHub
parent 5a61835812
commit f4e42ac3ef

View File

@@ -2,9 +2,9 @@
## Interfaces
Una de las características de diseño mas sutiles en Go son las interfaces. Después de leer esta sección, probablemente quedara impresionado por su implementación.
Una de las características de diseño más sutiles en Go son las interfaces. Después de leer esta sección, probablemente quedara impresionado por su implementación.
### Que es una interfaz?
### ¿Que es una interfaz?
En pocas palabras, una interfaz es un conjunto de métodos, que se usan para definir un conjunto de acciones.
@@ -19,6 +19,7 @@ Esta combinación de métodos es llamada interfaz, y es implementada por Student
### Tipo de Interfaces
Una interfaz define un grupo de métodos, entonces si un tipo implementa todos los métodos entonces nosotros decimos que ese tipo implementa la interfaz.
```
type Human struct {
name string
@@ -89,9 +90,10 @@ Tenga en cuenta que todos los tipos implementan la interfaz vacía `interface{}`
### Valor de una interfaz
Entonces, que tipo de valores se puede poner en una interfaz? Si definimos una variable como tipo interfaz, cualquier tipo que implemente la interfaz puede asignarse a esta variable.
Entonces, ¿qué tipo de valores se pueden poner en una interfaz? Si definimos una variable como tipo interfaz, cualquier tipo que implemente la interfaz puede asignarse a esta variable.
Al igual que en el ejemplo anterior, si definimos una variable m como la interfaz Men, entonces cualquier Student, Human o Employee puede ser asignado a m. Entonces podríamos tener una lista de Men, y cualquier tipo que implemente la interfaz Men puede agregarse a esa lista (slice). Sin embargo sea consciente que una lista de interfaces no tiene el mismo comportamiento que una lista de otros tipos.
```
package main
@@ -172,6 +174,7 @@ Una interfaz es un conjunto de métodos abstractos, y puede ser implementada por
### Interfaz vacía
Una interfaz vacía es una interfaz que no contiene ningún método, entonces todos los tipos implementan una interfaz vacía. Es muy útil cuando buscamos guardar todos los tipos en el mismo lugar, y es similar a void* en C.
```
// definimos una interfaz vacía
var a interface{}
@@ -188,12 +191,15 @@ 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 ¿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
}
```
```
Esto significa que cualquier tipo que implemente la interfaz Stringer puede ser pasada a fmt.Println como argumento. Vamos a probarlo.
```
package main
@@ -220,10 +226,12 @@ Esto significa que cualquier tipo que implemente la interfaz Stringer puede ser
```
Volviendo atrás al ejemplo de Box, podemos ver que Color también implementa la interfaz Stringer, por lo que somos capaces de personalizar el formato de impresión. Si no implementamos esa interfaz, fmt.Println imprimirá el tipo con el formato por defecto.
```
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 no tendrás que implementar Stringer.
### Tipos de variables en un interfaz
@@ -237,6 +245,7 @@ Go tiene la sintaxis `value, ok := element.(T)`. Esto comprueba si la variable e
Si el elemento es del tipo que esperamos, ok será true, en otro caso será false.
Veamos un ejemplo para verlo con más claridad.
```
package main
@@ -276,11 +285,13 @@ Veamos un ejemplo para verlo con más claridad.
}
}
```
Es bastante sencillo usar este patrón, pero si tenemos que verificar varios tipos, es mejor que usemos un `switch`.
- Verificación con un switch
Vamos a ver el uso de `switch` para reescribir el ejemplo anterior.
```
package main
@@ -329,14 +340,17 @@ Una cosa que deberíamos recordar es que `element.(type)` no puede ser usado fue
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.
```
type Interface interface {
sort.Interface // embebida sort.Interface
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.
@@ -348,38 +362,48 @@ Podemos ver que `sort.Interface` es una interfaz embebida, por lo que la interfa
Swap(i, j int)
}
```
Otro ejemplo es el de `io.ReadWriter` en el paquete `io`.
```
// io.ReadWriter
type ReadWriter interface {
Reader
Writer
}
```
### Reflexión
La reflexión en Go es usada para obtener información en tiempo de ejecución. Vamos a usar el paquete `reflect`, y este articulo oficial [articulo](http://golang.org/doc/articles/laws_of_reflection.html) explica como funciona la reflexión en Go.
Tenemos que realizar tres pasos para usar reflect. Primero, necesitamos convertir una interfaz en un tipo reflect types (reflect.Type o reflect.Value, depende en que situación nos encontremos).
```
t := reflect.TypeOf(i) // tomamos la meta-data de el tipo i, y usamos t para tomar todos los elementos
v := reflect.ValueOf(i) // tomamos el valor actual de el tipo i, y usamos v para cambiar este valor
```
Después de eso, necesitamos convertir el tipo reflect de el valor que tomamos a el tipo que necesitamos.
```
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type())
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á.
```
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1)
```
En lugar de eso, debemos usar el siguiente código para cambiar el valor de los tipos reflect.
```
var x float64 = 3.4
p := reflect.ValueOf(&x)