Szukaj…


Uwagi

Interfejsu nie można zaimplementować w odbiornikach wskaźnikowych, ponieważ *User nie jest User

Struktury

Go obsługuje typy zdefiniowane przez użytkownika w postaci struktur i aliasów typów. Struktury są typami złożonymi, a elementy składowe danych, które tworzą typ struktury, nazywane są polami . pole ma typ i nazwę, które muszą być niepotrzebne.

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

jest to również legalna składnia do definiowania struktur

type User struct {
    ID uint64
    FullName, Email string
}

user := new(User)

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

Wbudowane struktury

ponieważ struct jest również typem danych, może być używany jako pole anonimowe, zewnętrzna struktura może bezpośrednio uzyskiwać dostęp do pól wbudowanej struktury, nawet jeśli struktura pochodzi z innego pakietu. to zachowanie zapewnia sposób na wyprowadzenie części lub całości implementacji z innego typu lub zestawu typów.

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
}

Metody

W Go metodą jest

funkcja, która działa na zmienną określonego typu, zwaną odbiornikiem

odbiornikiem może być wszystko, nie tylko structs ale nawet function , typy aliasów dla typów wbudowanych, takich jak int , string , bool mogą mieć metodę, wyjątkiem od tej reguły jest to, że interfaces (omówione później) nie mogą mieć metod, ponieważ Interfejs jest abstrakcyjną definicją, a metoda jest implementacją, próbując wygenerować błąd kompilacji.

łącząc structs i methods , można uzyskać ścisły odpowiednik class w programowaniu obiektowym.

metoda w Go ma następujący podpis

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
}

Wskaźnik Vs Odbiornik wartości

odbiornik metody jest zwykle wskaźnikiem ze względu na wydajność, ponieważ nie wykonalibyśmy kopii instancji, tak jak w przypadku odbiornika wartości, jest to szczególnie prawdziwe, jeśli typem odbiornika jest struct. innym powodem, dla którego odbiornik powinien być wskaźnikiem, jest to, że możemy zmodyfikować dane, na które wskazuje odbiornik.

odbiornik wartości służy do uniknięcia modyfikacji danych, które zawiera odbiornik, odbiornik vaule może spowodować obniżenie wydajności, jeśli odbiornik jest dużą strukturą.

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

Interfejs i polimorfizm

Interfejsy zapewniają sposób określania zachowania obiektu, jeśli coś może to zrobić, można go tutaj użyć. interfejs definiuje zestaw metod, ale metody te nie zawierają kodu, ponieważ są abstrakcyjne lub implementacja jest pozostawiona użytkownikowi interfejsu. w przeciwieństwie do większości języków zorientowanych obiektowo interfejsy mogą zawierać zmienne w Go.

Polimorfizm jest istotą programowania obiektowego: zdolność do równego traktowania obiektów różnych typów, o ile przylegają do tego samego interfejsu. Interfejsy Go zapewniają tę funkcję w bardzo bezpośredni i intuicyjny sposób

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
Licencjonowany na podstawie CC BY-SA 3.0
Nie związany z Stack Overflow