Buscar..


Observaciones

La interfaz no se puede implementar con receptores de puntero porque *User no es User

Estructuras

Go admite tipos definidos por el usuario en forma de estructuras y alias de tipo. Las estructuras son tipos compuestos, los elementos componentes de los datos que constituyen el tipo de estructura se denominan campos . un campo tiene un tipo y un nombre que debe ser unqiue.

package main

type User struct {
    ID uint64
    FullName string
    Email    string
}

func main() {
    user := User{
        1,
        "Zelalem Mekonen",
        "[email protected]",
    }

    fmt.Println(user) // {1 Zelalem Mekonen [email protected]}
}

Esta es también una sintaxis legal para definir estructuras.

type User struct {
    ID uint64
    FullName, Email string
}

user := new(User)

user.ID = 1
user.FullName = "Zelalem Mekonen"
user.Email = "[email protected]"

Estructuras embebidas

Debido a que una estructura es también un tipo de datos, se puede usar como un campo anónimo, la estructura externa puede acceder directamente a los campos de la estructura incorporada incluso si la estructura proviene de un paquete diferente. este comportamiento proporciona una manera de derivar parte o la totalidad de su implementación de otro tipo o conjunto de tipos.

package main

type Admin struct {
    Username, Password string
}

type User struct {
    ID uint64
    FullName, Email string
    Admin // embedded struct
}

func main() {
    admin := Admin{
        "zola",
        "supersecretpassword",
    }

    user := User{
        1,
        "Zelalem Mekonen",
        "[email protected]",
        admin,
    }

    fmt.Println(admin) // {zola supersecretpassword}

    fmt.Println(user) // {1 Zelalem Mekonen [email protected] {zola supersecretpassword}}

    fmt.Println(user.Username) // zola

    fmt.Println(user.Password) // supersecretpassword
}

Métodos

En Go un método es

una función que actúa sobre una variable de cierto tipo, llamada el receptor

el receptor puede ser cualquier cosa, no solo structs sino incluso una function , tipos de alias para tipos integrados como int , string , bool puede tener un método, una excepción a esta regla es que las interfaces (que se explican más adelante) no pueden tener métodos, ya que interfaz es una definición abstracta y un método es una implementación, al intentar generar un error de compilación.

combinando structs y methods puede obtener un equivalente cercano de una class en programación orientada a objetos.

Un método en Go tiene la siguiente firma.

func (name receiverType) methodName(paramterList) (returnList) {}

package main

type Admin struct {
    Username, Password string
}

func (admin Admin) Delete() {
    fmt.Println("Admin Deleted")
}

type User struct {
    ID uint64
    FullName, Email string
    Admin
}

func (user User) SendEmail(email string) {
    fmt.Printf("Email sent to: %s\n", user.Email)
} 

func main() {
    admin := Admin{
        "zola",
        "supersecretpassword",
    }

    user := User{
        1,
        "Zelalem Mekonen",
        "[email protected]",
        admin,
    }

    user.SendEmail("Hello") // Email sent to: [email protected]

    admin.Delete() // Admin Deleted
}

Puntero Vs Valor receptor

El receptor de un método suele ser un puntero por motivos de rendimiento porque no haríamos una copia de la instancia, como sería el caso en el receptor de valores, esto es especialmente cierto si el tipo de receptor es una estructura. Otra razón para hacer que el receptor escriba un puntero sería para que pudiéramos modificar los datos a los que apunta el receptor.

se utiliza un receptor de valor para evitar la modificación de los datos que contiene el receptor, un receptor de vara puede causar un impacto en el rendimiento si el receptor es una estructura grande.

package main

type User struct {
    ID uint64
    FullName, Email string
}

// We do no require any special syntax to access field because receiver is a pointer
func (user *User) SendEmail(email string) {
    fmt.Printf("Sent email to: %s\n", user.Email)
}    

// ChangeMail will modify the users email because the receiver type is a ponter
func (user *User) ChangeEmail(email string) {
    user.Email = email;
}

func main() {
    user := User{
        1,
        "Zelalem Mekonen",
        "[email protected]",
    }

    user.SendEmail("Hello") // Sent email to: [email protected]

    user.ChangeEmail("[email protected]")

    fmt.Println(user.Email) // [email protected]
}

Interfaz y polimorfismo

Las interfaces proporcionan una manera de especificar el comportamiento de un objeto, si algo puede hacer esto, se puede usar aquí. una interfaz define un conjunto de métodos, pero estos métodos no contienen código, ya que son abstractos o se deja en manos del usuario de la interfaz. a diferencia de la mayoría de los lenguajes, las interfaces orientadas a objetos pueden contener variables en Go.

El polimorfismo es la esencia de la programación orientada a objetos: la capacidad de tratar objetos de diferentes tipos de manera uniforme siempre que se adhieran a la misma interfaz. Las interfaces Go proporcionan esta capacidad de una manera muy directa e intuitiva.

package main

type Runner interface {
    Run()
}

type Admin struct {
    Username, Password string
}

func (admin Admin) Run() {
    fmt.Println("Admin ==> Run()");
}

type User struct {
    ID uint64
    FullName, Email string
}

func (user User) Run() {
    fmt.Println("User ==> Run()")
}

// RunnerExample takes any type that fullfils the Runner interface
func RunnerExample(r Runner) {
    r.Run()
}

func main() {
    admin := Admin{
        "zola",
        "supersecretpassword",
    }

    user := User{
        1,
        "Zelalem Mekonen",
        "[email protected]",
    }

    RunnerExample(admin)

    RunnerExample(user)
    
}


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow