Estructuras e interfaces

11. Estructuras e interfaces#

11.1. Structs#

En Go las structs son colecciones de campos, podríamos pensar una struct cómo una clase que solo declara atributos (los campos).

type Direccion struct {
    calle, ciudad, provincia string
    numero                   uint
}

type Persona struct {
    nombre, apellido string
    edad             uint
    direccion        Direccion
}

Para acceder a un campo de una estructura, se usa la notación de punto, como lo hacemos para acceder a un atributo en Java.

var p1 Persona
p1.nombre = "Marcelo"
p1.edad = 27
p1.edad
27

También podemos declarar una variable de tipo struct de forma literal:

p2 := Persona{nombre: "Laura", apellido: "Medina", edad: 25}
{Laura Medina 25 {   0}}

11.1.1. Métodos#

Go no tiene clases como Java, sin embargo permite definir métodos sobre ciertos tipos.

Un método es una función con un argumento especial receptor . El receptor aparece en su propia lista de argumentos entre la palabra clave func y el nombre del método.

import "math"

type Vector struct {
    X, Y float64
}

func (v Vector) Modulo() float64 {
    return math.Sqrt(v.X*v.X + v.Y*v.Y)
}

func (v *Vector) Escalar(factor float64) {
    v.X *= factor
    v.Y *= factor
}

En este ejemplo, el método Modulo tiene un receptor de tipo Vector llamado v. Y el método Escalar recibe un puntero a Vector, ya que en este contexto es necesario contar con la referencia a la variable apuntada, ya que este método modifica el “estado” del receptor.

11.2. Interfaces#

Como mencionamos anteriormente, en Go existe el concepto de interfaces pero funcionan de forma algo diferente a como lo hacen en Java.

Un tipo interface se define como una conjunto de firmas de método. Un valor de ese tipo de interfaz, puede contener a cualquier valor que implemente (todos) esos métodos.

type Caminante interface {
    Avanzar(pasos int)
    Girar(grados float32)
}

Luego si un tipo implementa todos esos métodos:

func (p *Persona) Avanzar(pasos int) { /* ... */ }

func (p *Persona) Girar(grados float32) { /* ... */ }

Podemos pasar como parámetro una variable de tipo Persona siempre se espere un argumento de tipo Caminante.

func RealizarRecorrido(caminante Caminante) { /* ... */ }

p := Persona{}

RealizarRecorrido(p)