Övning – Använda structs
Det finns tillfällen då du behöver representera en samling fält i en struktur. När du till exempel behöver skriva ett löneprogram måste du använda en datastruktur för anställda. I Go kan du använda structs för att gruppera olika fält som kan bilda en post.
En struct i Go är en annan datatyp som kan innehålla noll eller fler fält av godtyckliga typer och representera dem som en enda entitet.
I det här avsnittet utforskar vi varför structs är viktiga och hur du använder dem.
Deklarera och initiera en struct
Om du vill deklarera en struct måste du använda nyckelordet struct
, tillsammans med listan över fält och deras typer som du vill att den nya datatypen ska ha. Om du till exempel vill definiera en anställds struct kan du använda följande kod:
type Employee struct {
ID int
FirstName string
LastName string
Address string
}
Sedan kan du deklarera en variabel med den nya typen som du vanligtvis gör med andra typer, så här:
var john Employee
Och om du vill deklarera och initiera en variabel samtidigt kan du göra det på följande sätt:
employee := Employee{1001, "John", "Doe", "Doe's Street"}
Observera att du måste ange ett värde för vart och ett av fälten från structen. Men det kan vara problematiskt ibland. Du kan också vara mer specifik om de fält som du vill initiera i en struct:
employee := Employee{LastName: "Doe", FirstName: "John"}
Observera att från föregående instruktion spelar det ingen roll vilken ordning du tilldelar värden till varje fält. Dessutom spelar det ingen roll om du inte anger något värde för något annat fält. Go tilldelar ett standardvärde beroende på fältdatatypen.
Om du vill komma åt enskilda fält i en struct kan du göra det med hjälp av punkt notationen (.
), som i det här exemplet:
employee.ID = 1001
fmt.Println(employee.FirstName)
Slutligen kan du använda operatorn &
för att ge en pekare till structen, som följande kod visar:
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)
}
När du kör föregående kod visas följande utdata:
{0 John Doe }
{0 David Doe }
Observera hur structen blir föränderlig när du använder pekare.
Struct-inbäddning
Med Structs i Go kan du bädda in en annan struct i en struct. Det kommer att finnas tillfällen då du vill minska upprepningen och återanvända en gemensam struct. Anta till exempel att du vill omstrukturera den tidigare koden så att den har en datatyp för en anställd och en annan för en entreprenör. Du kan ha en Person
struct som innehåller vanliga fält, som det här exemplet:
type Person struct {
ID int
FirstName string
LastName string
Address string
}
Du kan sedan deklarera andra typer som bäddar in en Person
typ, till exempel en Employee
och en Contractor
. Om du vill bädda in en annan struct skapar du ett nytt fält, som det här exemplet:
type Employee struct {
Information Person
ManagerID int
}
Men för att referera till ett fält från structen Person
måste du inkludera Information
fältet från en variabel för anställda, som i det här exemplet:
var employee Employee
employee.Information.FirstName = "John"
Om du omstrukturerar kod som vi gör skulle det bryta vår kod. Du kan också inkludera ett nytt fält med samma namn som den struct som du bäddar in, som i det här exemplet:
type Employee struct {
Person
ManagerID int
}
Som en demonstration kan du använda följande kod:
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)
}
Observera hur du kommer åt fältet FirstName
från en Employee
struct utan att behöva ange Person
fältet eftersom det bäddar in alla fält automatiskt. Men när du initierar en struct måste du vara specifik om vilket fält du vill tilldela ett värde till.
Koda och avkoda structs med JSON
Slutligen kan du använda structs för att koda och avkoda data i JSON. Go har utmärkt stöd för JSON-formatet, och det ingår redan i standardbibliotekspaketen.
Du kan också göra saker som att byta namn på namnet på ett fält från structen. Anta till exempel att du inte vill att JSON-utdata ska visas FirstName
utan helt enkelt name
eller ignorera tomma fält. Du kan använda fälttaggar som det här exemplet visar:
type Person struct {
ID int
FirstName string `json:"name"`
LastName string
Address string `json:"address,omitempty"`
}
Om du sedan vill koda en struct till JSON använder json.Marshal
du funktionen. Och om du vill avkoda en JSON-sträng till en datastruktur använder json.Unmarshal
du funktionen. Här är ett exempel som sätter ihop allt, kodar en matris med anställda till JSON och avkodar utdata till en ny variabel:
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)
}
När du kör föregående kod visas följande utdata:
[{"ID":0,"name":"John","LastName":"Doe","ManagerID":0},{"ID":0,"name":"David","LastName":"Campbell","ManagerID":0}]
[{{0 John Doe } 0} {{0 David Campbell } 0}]