Sök…
Introduktion
Kartor är datatyper som används för att lagra oordnade nyckelvärdespar, så att det är mycket effektivt att slå upp värdet associerat med en given nyckel. Nycklar är unika. Den underliggande datastrukturen växer efter behov för att rymma nya element, så programmeraren behöver inte oroa sig för minneshantering. De liknar det som andra språk kallar hashtabeller, ordböcker eller associerande matriser.
Syntax
- var mapName map [KeyType] ValueType // deklarera en karta
- var mapName = map [KeyType] ValueType {} // förklara och tilldela en tom karta
- var mapName = map [KeyType] ValueType {key1: val1, key2: val2} // deklarera och tilldela en karta
- mapName: = make (map [KeyType] ValueType) // deklarera och initialisera standardstorlekskarta
- mapName: = make (karta [KeyType] ValueType, length) // deklarera och initialisera längdstorlekskarta
- mapName: = map [KeyType] ValueType {} // auto-deklarera och tilldela en tom karta med: =
- mapName: = map [KeyType] ValueType {key1: value1, key2: value2} // auto-deklarera och tilldela en karta med: =
- värde: = mapName [nyckel] // Få värde för nyckel
- value, hasKey: = mapName [key] // Hämta värde per nyckel, 'hasKey' är 'true' om nyckel finns i kartan
- mapName [key] = värde // Ställ in värde för nyckel
Anmärkningar
Go finns en inbyggd map
typ som implementerar en hash-tabell. Kartor är Gos inbyggda associativa datatyp (även kallad hashes eller ordböcker på andra språk).
Förklaring och initialisering av en karta
Du definierar en karta med hjälp av sökord map
, följt av de typer av sina nycklar och dess värden:
// Keys are ints, values are ints.
var m1 map[int]int // initialized to nil
// Keys are strings, values are ints.
var m2 map[string]int // initialized to nil
Kartor är referenstyper, och när de väl definierats har de ett nollvärde på nil
. Skrivningar till nollkartor kommer att få panik och läsningar kommer alltid att returnera nollvärdet.
För att initialisera en karta använder du make
funktionen:
m := make(map[string]int)
Med tvåparameterns form av make
är det möjligt att ange en initial inmatningskapacitet för kartan och åsidosätta standardkapaciteten:
m := make(map[string]int, 30)
Alternativt kan du förklara en karta, initiera den till dess nollvärde och sedan tilldela ett bokstavsvärde till det senare, vilket hjälper om du marshalerar strukturen till json och därmed producerar en tom karta vid retur.
m := make(map[string]int, 0)
Du kan också skapa en karta och ställa in dess initiala värde med lockiga parenteser ( {}
).
var m map[string]int = map[string]int{"Foo": 20, "Bar": 30}
fmt.Println(m["Foo"]) // outputs 20
Alla följande påståenden resulterar i att variabeln är bunden till samma värde.
// Declare, initializing to zero value, then assign a literal value.
var m map[string]int
m = map[string]int{}
// Declare and initialize via literal value.
var m = map[string]int{}
// Declare via short variable declaration and initialize with a literal value.
m := map[string]int{}
Vi kan också använda en bokstavlig karta för att skapa en ny karta med några initiala nyckel- / värdepar .
Nyckeltypen kan vara vilken som helst jämförbar typ; särskilt utesluter detta funktioner, kartor och skivor . Värdetypen kan vara valfri typ, inklusive anpassade typer eller interface{}
.
type Person struct {
FirstName string
LastName string
}
// Declare via short variable declaration and initialize with make.
m := make(map[string]Person)
// Declare, initializing to zero value, then assign a literal value.
var m map[string]Person
m = map[string]Person{}
// Declare and initialize via literal value.
var m = map[string]Person{}
// Declare via short variable declaration and initialize with a literal value.
m := map[string]Person{}
Skapa en karta
Man kan förklara och initiera en karta i ett enda uttalande med hjälp av en sammansatt bokstav .
Med automatisk typ kortvariabel deklaration:
mapIntInt := map[int]int{10: 100, 20: 100, 30: 1000}
mapIntString := map[int]string{10: "foo", 20: "bar", 30: "baz"}
mapStringInt := map[string]int{"foo": 10, "bar": 20, "baz": 30}
mapStringString := map[string]string{"foo": "one", "bar": "two", "baz": "three"}
Samma kod, men med variabeltyper:
var mapIntInt = map[int]int{10: 100, 20: 100, 30: 1000}
var mapIntString = map[int]string{10: "foo", 20: "bar", 30: "baz"}
var mapStringInt = map[string]int{"foo": 10, "bar": 20, "baz": 30}
var mapStringString = map[string]string{"foo": "one", "bar": "two", "baz": "three"}
Du kan också inkludera dina egna strukturer på en karta:
Du kan använda anpassade typer som värde:
// Custom struct types
type Person struct {
FirstName, LastName string
}
var mapStringPerson = map[string]Person{
"john": Person{"John", "Doe"},
"jane": Person{"Jane", "Doe"}}
mapStringPerson := map[string]Person{
"john": Person{"John", "Doe"},
"jane": Person{"Jane", "Doe"}}
Din struktur kan också vara nyckeln till kartan:
type RouteHit struct {
Domain string
Route string
}
var hitMap = map[RouteHit]int{
RouteHit{"example.com","/home"}: 1,
RouteHit{"example.com","/help"}: 2}
hitMap := map[RouteHit]int{
RouteHit{"example.com","/home"}: 1,
RouteHit{"example.com","/help"}: 2}
Du kan skapa en tom karta helt enkelt genom att inte ange något värde inom parentes {}
.
mapIntInt := map[int]int{}
mapIntString := map[int]string{}
mapStringInt := map[string]int{}
mapStringString := map[string]string{}
mapStringPerson := map[string]Person{}
Du kan skapa och använda en karta direkt utan att behöva tilldela den till en variabel. Du måste dock ange både deklarationen och innehållet.
// using a map as argument for fmt.Println()
fmt.Println(map[string]string{
"FirstName": "John",
"LastName": "Doe",
"Age": "30"})
// equivalent to
data := map[string]string{
"FirstName": "John",
"LastName": "Doe",
"Age": "30"}
fmt.Println(data)
Nollvärde på en karta
Nollvärdet på en map
är nil
och har en längd på 0
.
var m map[string]string
fmt.Println(m == nil) // true
fmt.Println(len(m) ==0) // true
En nil
har inga nycklar eller kan inte läggas till nycklar. En nil
uppför sig som en tom karta om den läses från men orsakar panik för körning om den skrivs till.
var m map[string]string
// reading
m["foo"] == "" // true. Remember "" is the zero value for a string
_, ok = m["foo"] // ok == false
// writing
m["foo"] = "bar" // panic: assignment to entry in nil map
Du bör inte försöka läsa från eller skriva till en karta med nollvärde. Inleda istället kartan (med make
eller tilldelning) innan du använder den.
var m map[string]string
m = make(map[string]string) // OR m = map[string]string{}
m["foo"] = "bar"
Iterera elementen på en karta
import fmt
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for key, value := range people {
fmt.Println("Name:", key, "Age:", value)
}
Observera att när iterering över en karta med en avståndsslinga är iterationsordningen inte specificerad och garanteras inte vara densamma från en iteration till nästa.
Du kan också kassera antingen nycklarna eller värdena på kartan om du bara vill ta tag i knapparna eller bara greppa värden.
Iterera nycklarna på en karta
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for key, _ := range people {
fmt.Println("Name:", key)
}
Om du bara letar efter nycklarna, eftersom de är det första värdet, kan du helt enkelt släppa understrecket:
for key := range people {
fmt.Println("Name:", key)
}
Observera att när iterering över en karta med en avståndsslinga är iterationsordningen inte specificerad och garanteras inte vara densamma från en iteration till nästa.
Radera ett kartelement
Den delete
inbyggd funktion tar bort elementet med den angivna nyckeln från en karta.
people := map[string]int{"john": 30, "jane": 29}
fmt.Println(people) // map[john:30 jane:29]
delete(people, "john")
fmt.Println(people) // map[jane:29]
Om map
är nil
eller det inte finns något sådant element har delete
ingen effekt.
people := map[string]int{"john": 30, "jane": 29}
fmt.Println(people) // map[john:30 jane:29]
delete(people, "notfound")
fmt.Println(people) // map[john:30 jane:29]
var something map[string]int
delete(something, "notfound") // no-op
Räkna kartelement
Den inbyggda funktionen len
returnerar antalet element på en map
m := map[string]int{}
len(m) // 0
m["foo"] = 1
len(m) // 1
Om en variabel pekar på en nil
karta, returnerar len
0.
var m map[string]int
len(m) // 0
Samtidig åtkomst av kartor
Kartor i gång är inte säkra för samtidighet. Du måste ta ett lås för att läsa och skriva om dem om du kommer åt dem samtidigt. Vanligtvis är det bästa alternativet att använda sync.RWMutex
eftersom du kan ha läs- och skrivlås. Men en sync.Mutex
kan också användas.
type RWMap struct {
sync.RWMutex
m map[string]int
}
// Get is a wrapper for getting the value from the underlying map
func (r RWMap) Get(key string) int {
r.RLock()
defer r.RUnlock()
return r.m[key]
}
// Set is a wrapper for setting the value of a key in the underlying map
func (r RWMap) Set(key string, val int) {
r.Lock()
defer r.Unlock()
r.m[key] = val
}
// Inc increases the value in the RWMap for a key.
// This is more pleasant than r.Set(key, r.Get(key)++)
func (r RWMap) Inc(key string) {
r.Lock()
defer r.Unlock()
r.m[key]++
}
func main() {
// Init
counter := RWMap{m: make(map[string]int)}
// Get a Read Lock
counter.RLock()
_ = counter.["Key"]
counter.RUnlock()
// the above could be replaced with
_ = counter.Get("Key")
// Get a write Lock
counter.Lock()
counter.m["some_key"]++
counter.Unlock()
// above would need to be written as
counter.Inc("some_key")
}
Avvägningen av omslagsfunktionerna är mellan allmänhetens åtkomst till den underliggande kartan och att använda lämpliga lås korrekt.
Skapa kartor med skivor som värden
m := make(map[string][]int)
Åtkomst till en icke-existerande nyckel kommer att returnera en nollskiva som ett värde. Eftersom nollskivor fungerar som skivor med noll längd när de används med append
eller andra inbyggda funktioner behöver du normalt inte kontrollera om en nyckel finns:
// m["key1"] == nil && len(m["key1"]) == 0
m["key1"] = append(m["key1"], 1)
// len(m["key1"]) == 1
Om du tar bort en nyckel från kartan återgår nyckeln till en nollskiva:
delete(m, "key1")
// m["key1"] == nil
Sök efter element på en karta
För att få ett värde från kartan måste du bara göra något som: 00
value := mapName[ key ]
Om kartan innehåller nyckeln returnerar den motsvarande värde.
Om inte, returnerar det nollvärdet för kartans värdetyp ( 0
om kartan med int
värden, ""
om kartan över string
...)
m := map[string]string{"foo": "foo_value", "bar": ""}
k := m["foo"] // returns "foo_value" since that is the value stored in the map
k2 := m["bar"] // returns "" since that is the value stored in the map
k3 := m["nop"] // returns "" since the key does not exist, and "" is the string type's zero value
För att skilja mellan tomma värden och icke-existerande nycklar kan du använda det andra returnerade värdet på kartåtkomst (med samma value, hasKey := map["key"]
).
Detta andra värde är boolean
och kommer att vara:
-
true
när värdet finns på kartan, -
false
när kartan inte innehåller den angivna nyckeln.
Titta på följande exempel:
value, hasKey = m[ key ]
if hasKey {
// the map contains the given key, so we can safely use the value
// If value is zero-value, it's because the zero-value was pushed to the map
} else {
// The map does not have the given key
// the value will be the zero-value of the map's type
}
Iterera värdena på en karta
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for _, value := range people {
fmt.Println("Age:", value)
}
Observera att när iterering över en karta med en avståndsslinga är iterationsordningen inte specificerad och garanteras inte vara densamma från en iteration till nästa.
Kopiera en karta
Liksom skivor har kartor referenser till en underliggande datastruktur. Så genom att tilldela dess värde till en annan variabel kommer endast referensen att skickas. För att kopiera kartan är det nödvändigt att skapa en ny karta och kopiera varje värde:
// Create the original map
originalMap := make(map[string]int)
originalMap["one"] = 1
originalMap["two"] = 2
// Create the target map
targetMap := make(map[string]int)
// Copy from the original map to the target map
for key, value := range originalMap {
targetMap[key] = value
}
Använda en karta som en uppsättning
Vissa språk har en ursprunglig struktur för uppsättningar. För att göra en uppsättning i Go är det bästa sättet att använda en karta från värdetyp för uppsättningen till en tom struktur ( map[Type]struct{}
).
Till exempel med strängar:
// To initialize a set of strings:
greetings := map[string]struct{}{
"hi": {},
"hello": {},
}
// To delete a value:
delete(greetings, "hi")
// To add a value:
greetings["hey"] = struct{}{}
// To check if a value is in the set:
if _, ok := greetings["hey"]; ok {
fmt.Println("hey is in greetings")
}