Recherche…


Remarques

L'interface ne peut pas être implémentée avec les récepteurs de pointeurs car *User n'est pas un User

Structs

Go prend en charge les types définis par l'utilisateur sous la forme de structures et d'alias de type. Les structures sont des types composites, les composants de données constituant le type de structure sont appelés champs . un champ a un type et un nom qui doit être 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]}
}

c'est aussi une syntaxe légale pour définir des structures

type User struct {
    ID uint64
    FullName, Email string
}

user := new(User)

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

Structures intégrées

Comme une structure est aussi un type de données, elle peut être utilisée comme un champ anonyme, la structure externe peut accéder directement aux champs de la structure intégrée même si la structure provient d’un package différent. Ce comportement permet de dériver tout ou partie de votre implémentation à partir d'un autre type ou d'un ensemble de types.

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
}

Les méthodes

En Go une méthode est

une fonction qui agit sur une variable d'un certain type, appelée le récepteur

le receveur peut être n'importe quoi, non seulement des structs mais même une function , les types d’alias pour les types intégrés tels que int , string , bool peuvent avoir une méthode, une exception à cette règle est que les interfaces interface est une définition abstraite et une méthode est une implémentation, essayant de générer une erreur de compilation.

En combinant des structs et des methods vous pouvez obtenir un équivalent proche d'une class en programmation orientée objet.

une méthode dans Go a la signature suivante

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
}

Pointeur Vs Value Receiver

le récepteur d'une méthode est généralement un pointeur pour des raisons de performances car nous ne ferions pas de copie de l'instance, comme ce serait le cas dans le récepteur de valeur, ceci est particulièrement vrai si le type de récepteur est une structure. une autre raison pour que le récepteur soit un pointeur serait de pouvoir modifier les données pointées par le récepteur.

un récepteur de valeur est utilisé pour éviter la modification des données contenues dans le récepteur, un récepteur de vaule peut provoquer une baisse de performance si le récepteur est une structure volumineuse.

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

Interface et polymorphisme

Les interfaces permettent de spécifier le comportement d'un objet, si quelque chose peut le faire, il peut être utilisé ici. une interface définit un ensemble de méthodes, mais ces méthodes ne contiennent pas de code car elles sont abstraites ou l'implémentation est laissée à l'utilisateur de l'interface. Contrairement à la plupart des langages orientés objet, les interfaces peuvent contenir des variables dans Go.

Le polymorphisme est l'essence même de la programmation orientée objet: la capacité à traiter des objets de types différents de manière uniforme tant qu'ils adhèrent à la même interface. Les interfaces Go offrent cette fonctionnalité de manière très directe et intuitive

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
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow