Ricerca…


Osservazioni

L'interfaccia non può essere implementata con i ricevitori puntatore perché *User non è User

Structs

Go supporta i tipi definiti dall'utente sotto forma di strutture e digita alias. le strutture sono tipi compositi, le parti componenti dei dati che costituiscono il tipo di struttura sono chiamate campi . un campo ha un tipo e un nome che deve essere 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]}
}

questa è anche una sintassi legale per definire le strutture

type User struct {
    ID uint64
    FullName, Email string
}

user := new(User)

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

Strutture incorporate

poiché una struct è anche un tipo di dati, può essere usata come un campo anonimo, la struct esterna può accedere direttamente ai campi della struct incorporata anche se la struct proviene da un pacchetto diffrent. questo comportamento fornisce un modo per ricavare parte o tutta l'implementazione da un altro tipo o da un insieme di tipi.

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
}

metodi

In Go a method is

una funzione che agisce su una variabile di un certo tipo, chiamata ricevitore

il ricevitore può essere qualsiasi cosa, non solo structs ma anche una function , i tipi di alias per i tipi built-in come int , string , bool possono avere un metodo, un'eccezione a questa regola è che le interfaces (discusse più tardi) non possono avere metodi, poiché l'interfaccia è una definizione astratta e un metodo è un'implementazione, provando a generare un errore di compilazione.

combinando le structs e i methods è possibile ottenere un equivalente eqivalente di una class nella programmazione orientata agli oggetti.

un metodo in Go ha la seguente 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
}

Pointer Vs Value receiver

il ricevitore di un metodo è di solito un puntatore per il motivo delle prestazioni perché non faremo una copia dell'istanza, come nel caso del ricevitore di valore, ciò è particolarmente vero se il tipo di destinatario è una struttura. un motivo in più per fare in modo che il ricevitore digiti un puntatore sarebbe in modo da poter modificare i dati a cui punta il ricevitore.

un ricevitore di valore viene utilizzato per evitare la modifica dei dati contenuti nel ricevitore, un ricevitore di vaule può causare un colpo di prestazioni se il ricevitore è una struttura di grandi dimensioni.

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]
}

Interfaccia e polimorfismo

Le interfacce forniscono un modo per specificare il comportamento di un oggetto, se qualcosa può farlo, allora può essere usato qui. un'interfaccia definisce un insieme di metodi, ma questi metodi non contengono codice in quanto sono astratti o l'implementazione è lasciata all'utente dell'interfaccia. a differenza della maggior parte delle interfacce linguistiche orientate agli oggetti possono contenere variabili in Go.

Il polimorfismo è l'essenza della programmazione orientata agli oggetti: la capacità di trattare oggetti di tipi diversi in modo uniforme purché aderiscano alla stessa interfaccia. Le interfacce Go forniscono questa funzionalità in modo molto diretto e intuitivo

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow