Cvičení – použití struktur

Dokončeno

Někdy potřebujete reprezentovat kolekci polí v jedné struktuře. Pokud například potřebujete napsat mzdový program, musíte použít datovou strukturu zaměstnanců. V go můžete pomocí struktur seskupit různá pole, která by mohla vytvořit záznam.

Struktura v Go je jiný datový typ, který může obsahovat nula nebo více polí libovolných typů a představuje je jako jedna entita.

V této části prozkoumáme, proč jsou struktury nezbytné a jak je používat.

Deklarace a inicializace struktury

Chcete-li deklarovat strukturu, musíte použít struct klíčové slovo spolu se seznamem polí a jejich typy, které chcete mít nový datový typ. Například k definování struktury zaměstnance můžete použít následující kód:

type Employee struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

Pak můžete deklarovat proměnnou s novým typem, jak byste to obvykle dělali s jinými typy, například takto:

var john Employee

A pokud chcete deklarovat a inicializovat proměnnou současně, můžete to udělat tímto způsobem:

employee := Employee{1001, "John", "Doe", "Doe's Street"}

Všimněte si, že je nutné zadat hodnotu pro každé pole ze struktury. Ale to může být někdy problematické. Případně můžete být konkrétnější o polích, která chcete inicializovat ve struktuře:

employee := Employee{LastName: "Doe", FirstName: "John"}

Všimněte si, že z předchozího příkazu nezáleží na pořadí, ve které přiřadíte hodnoty jednotlivým polím. Nezáleží také na tom, jestli nezadáte hodnotu pro žádné jiné pole. Go přiřadí výchozí hodnotu v závislosti na datovém typu pole.

Pokud chcete získat přístup k jednotlivým polím struktury, můžete to udělat pomocí zápisu tečky (.), například v tomto příkladu:

employee.ID = 1001
fmt.Println(employee.FirstName)

Nakonec můžete pomocí operátoru & vytvořit ukazatel na strukturu, například následující kód ukazuje:

package main

import "fmt"

type Employee struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

func main() {
    employee := Employee{LastName: "Doe", FirstName: "John"}
    fmt.Println(employee)
    employeeCopy := &employee
    employeeCopy.FirstName = "David"
    fmt.Println(employee)
}

Při spuštění předchozího kódu se zobrazí následující výstup:

{0 John Doe }
{0 David Doe }

Všimněte si, jak se struktura při použití ukazatelů změní na proměnlivou strukturu.

Vkládání struktur

Struktury v go umožňují vložit jinou strukturu do struktury. Existují situace, kdy chcete snížit opakování a znovu použít společnou strukturu. Řekněme například, že chcete refaktorovat předchozí kód tak, aby měl datový typ pro zaměstnance a jiný pro dodavatele. Můžete mít Person strukturu, která obsahuje běžná pole, například v tomto příkladu:

type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

Pak můžete deklarovat jiné typy, které vkládají Person typ, například typ Employee a Contractor. Pokud chcete vložit jinou strukturu, vytvořte nové pole, například v tomto příkladu:

type Employee struct {
    Information Person
    ManagerID   int
}

Pokud ale chcete odkazovat na pole ze Person struktury, budete muset zahrnout Information pole z proměnné zaměstnance, například v tomto příkladu:

var employee Employee
employee.Information.FirstName = "John"

Pokud refaktorujete kód, jako bychom to dělali, přerušilo by to náš kód. Alternativně můžete zahrnout nové pole se stejným názvem struktury, kterou vkládáte, například v tomto příkladu:

type Employee struct {
    Person
    ManagerID int
}

Jako ukázku můžete použít následující kód:

package main

import "fmt"

type Person struct {
    ID        int
    FirstName string
    LastName  string
    Address   string
}

type Employee struct {
    Person
    ManagerID int
}

type Contractor struct {
    Person
    CompanyID int
}

func main() {
    employee := Employee{
        Person: Person{
            FirstName: "John",
        },
    }
    employee.LastName = "Doe"
    fmt.Println(employee.FirstName)
}

Všimněte si, jak se k poli dostanete FirstName ze Employee struktury, aniž byste museli zadat Person pole, protože vkládá všechna jeho pole automaticky. Když ale inicializujete strukturu, musíte být specifická pro pole, ke kterému chcete přiřadit hodnotu.

Kódování a dekódování struktur pomocí JSON

Nakonec můžete pomocí struktur kódovat a dekódovat data ve formátu JSON. Go má vynikající podporu pro formát JSON a je již součástí standardních balíčků knihovny.

Můžete také udělat věci, jako je přejmenování názvu pole ze struktury. Řekněme například, že nechcete, aby výstup JSON zobrazoval FirstName , ale jednoduše name nebo ignoroval prázdná pole. Značky polí, jako je tento příklad, můžete použít:

type Person struct {
    ID        int    
    FirstName string `json:"name"`
    LastName  string
    Address   string `json:"address,omitempty"`
}

Potom k kódování struktury do FORMÁTU JSON použijete json.Marshal funkci. A k dekódování řetězce JSON do datové struktury použijete json.Unmarshal funkci. Tady je příklad, který všechno spojí dohromady, zakóduje pole zaměstnanců do FORMÁTU JSON a dekóduje výstup do nové proměnné:

package main

import (
    "encoding/json"
    "fmt"
)

type Person struct {
    ID        int
    FirstName string `json:"name"`
    LastName  string
    Address   string `json:"address,omitempty"`
}

type Employee struct {
    Person
    ManagerID int
}

type Contractor struct {
    Person
    CompanyID int
}

func main() {
    employees := []Employee{
        Employee{
            Person: Person{
                LastName: "Doe", FirstName: "John",
            },
        },
        Employee{
            Person: Person{
                LastName: "Campbell", FirstName: "David",
            },
        },
    }

    data, _ := json.Marshal(employees)
    fmt.Printf("%s\n", data)

    var decoded []Employee
    json.Unmarshal(data, &decoded)
    fmt.Printf("%v", decoded)
}

Při spuštění předchozího kódu se zobrazí následující výstup:

[{"ID":0,"name":"John","LastName":"Doe","ManagerID":0},{"ID":0,"name":"David","LastName":"Campbell","ManagerID":0}]
[{{0 John Doe } 0} {{0 David Campbell } 0}]