Suche…
Einführung
Maps sind Datentypen, die zum Speichern von ungeordneten Schlüsselwertpaaren verwendet werden, so dass das Nachschlagen des mit einem bestimmten Schlüssel verknüpften Werts sehr effizient ist. Schlüssel sind einzigartig. Die zugrunde liegende Datenstruktur wächst nach Bedarf, um neue Elemente aufzunehmen, sodass sich der Programmierer nicht um die Speicherverwaltung kümmern muss. Sie ähneln dem, was andere Sprachen Hashtabellen, Wörterbücher oder assoziative Arrays nennen.
Syntax
- var mapName map [KeyType] ValueType // eine Map deklarieren
- var mapName = map [KeyType] ValueType {} // Eine leere Map deklarieren und zuweisen
- var mapName = map [KeyType] ValueType {key1: val1, key2: val2} // Deklarieren und Zuordnen einer Map
- mapName: = make (map [KeyType] ValueType) // deklarieren und initialisieren Sie eine Standardgröße
- mapName: = machen (map [KeyType] Valuetype, Länge) // deklarieren und Länge Größe Karte initialisieren
- mapName: = map [KeyType] ValueType {} // Automatische Deklaration und Zuordnung einer leeren Map mit: =
- mapName: = map [KeyType] ValueType {key1: value1, key2: value2} // Automatische Deklaration und Zuordnung einer Map mit: =
- value: = mapName [key] // Wert nach Schlüssel abrufen
- value, hasKey: = mapName [key] // Wert nach Schlüssel abrufen, 'hasKey' ist 'true', wenn der Schlüssel in der Map vorhanden ist
- mapName [Schlüssel] = Wert // Wert nach Schlüssel setzen
Bemerkungen
Go bietet einen integrierten map
, der eine Hashtabelle implementiert . Maps sind der integrierte assoziative Datentyp von Go (in anderen Sprachen auch Hashes oder Wörterbücher genannt).
Eine Karte deklarieren und initialisieren
Sie definieren eine Map mit der Keyword- map
, gefolgt von den Schlüsseltypen und deren Werten:
// 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
Karten sind Referenztypen. Sobald sie definiert sind, haben sie den Wert nil
. Bei Schreibvorgängen auf Nullkarten gerät Panik in Betracht, und Lesevorgänge geben immer den Nullwert zurück.
Um eine Karte zu initialisieren, verwenden Sie die make
Funktion:
m := make(map[string]int)
Mit der Zwei-Parameter-Form von make
ist es möglich, eine anfängliche Eingabekapazität für die Karte anzugeben, wodurch die Standardkapazität überschrieben wird:
m := make(map[string]int, 30)
Alternativ können Sie eine Map deklarieren, sie auf ihren Nullwert initialisieren und ihr später einen literalen Wert zuweisen. Dies ist hilfreich, wenn Sie die Struktur in json marshallieren und bei der Rückkehr eine leere Map erzeugen.
m := make(map[string]int, 0)
Sie können auch eine Karte erstellen und ihren ursprünglichen Wert mit geschweiften Klammern ( {}
) festlegen.
var m map[string]int = map[string]int{"Foo": 20, "Bar": 30}
fmt.Println(m["Foo"]) // outputs 20
Alle folgenden Anweisungen führen dazu, dass die Variable an denselben Wert gebunden ist.
// 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{}
Wir können auch ein Kartenliteral verwenden , um eine neue Karte mit einigen anfänglichen Schlüssel / Wert-Paaren zu erstellen .
Der Schlüsseltyp kann ein beliebiger vergleichbarer Typ sein. Dies gilt insbesondere für Funktionen, Karten und Slices . Der Werttyp kann ein beliebiger Typ sein, einschließlich benutzerdefinierter Typen oder 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{}
Eine Karte erstellen
Mit einem zusammengesetzten Literal kann eine Map in einer einzelnen Anweisung deklariert und initialisiert werden.
Verwendung des automatischen Typs Kurze Variablendeklaration:
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"}
Gleicher Code, jedoch mit Variablentypen:
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"}
Sie können auch eigene Strukturen in eine Karte einfügen:
Sie können benutzerdefinierte Typen als Wert verwenden:
// 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"}}
Ihre Struktur kann auch der Schlüssel zur Karte sein:
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}
Sie können eine leere Map erstellen, indem Sie einfach keinen Wert in die Klammern {}
.
mapIntInt := map[int]int{}
mapIntString := map[int]string{}
mapStringInt := map[string]int{}
mapStringString := map[string]string{}
mapStringPerson := map[string]Person{}
Sie können eine Map direkt erstellen und verwenden, ohne sie einer Variablen zuordnen zu müssen. Sie müssen jedoch sowohl die Deklaration als auch den Inhalt angeben.
// 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)
Nullwert einer Karte
Der Nullwert einer map
ist nil
und hat eine Länge von 0
.
var m map[string]string
fmt.Println(m == nil) // true
fmt.Println(len(m) ==0) // true
Eine nil
Karte hat weder Schlüssel noch können Schlüssel hinzugefügt werden. Eine nil
Map verhält sich wie eine leere Map, wenn gelesen wird, verursacht jedoch eine Laufzeitpanik, wenn geschrieben wird.
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
Sie sollten nicht versuchen, aus einer Nullwertzuordnung zu lesen oder in diese zu schreiben. Initialisieren Sie stattdessen die Karte (mit make
oder Zuweisung), bevor Sie sie verwenden.
var m map[string]string
m = make(map[string]string) // OR m = map[string]string{}
m["foo"] = "bar"
Iteration der Elemente einer Karte
import fmt
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for key, value := range people {
fmt.Println("Name:", key, "Age:", value)
}
Beachten Sie, dass beim Durchlaufen einer Karte mit einer Bereichsschleife die Iterationsreihenfolge nicht angegeben wird und nicht von einer Iteration zur nächsten garantiert ist.
Sie können auch die Schlüssel oder die Werte der Karte verwerfen, wenn Sie nur nach Schlüsseln oder Werten suchen.
Iteration der Schlüssel einer Karte
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for key, _ := range people {
fmt.Println("Name:", key)
}
Wenn Sie nur nach den Schlüsseln suchen, da sie der erste Wert sind, können Sie den Unterstrich einfach fallen lassen:
for key := range people {
fmt.Println("Name:", key)
}
Beachten Sie, dass beim Durchlaufen einer Karte mit einer Bereichsschleife die Iterationsreihenfolge nicht angegeben wird und nicht von einer Iteration zur nächsten garantiert ist.
Kartenelement löschen
Die integrierte delete
entfernt das Element mit dem angegebenen Schlüssel aus einer Karte.
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]
Wenn die map
nil
oder kein solches Element vorhanden ist, hat das delete
keine Auswirkung.
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
Kartenelemente zählen
Die eingebaute Funktion len
gibt die Anzahl der Elemente in einer map
m := map[string]int{}
len(m) // 0
m["foo"] = 1
len(m) // 1
Wenn eine Variable auf eine nil
Karte zeigt, gibt len
0 zurück.
var m map[string]int
len(m) // 0
Gleichzeitiger Zugriff auf Karten
Karten in go sind für Parallelität nicht sicher. Sie müssen eine Sperre zum Lesen und Schreiben auf sie nehmen, wenn Sie gleichzeitig darauf zugreifen. Normalerweise ist die beste Option die Verwendung von sync.RWMutex
da Sie Lese- und Schreibsperren haben können. Es kann jedoch auch ein sync.Mutex
verwendet werden.
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")
}
Der Kompromiss zwischen den Wrapper-Funktionen besteht zwischen dem öffentlichen Zugriff auf die zugrunde liegende Karte und der korrekten Verwendung der entsprechenden Sperren.
Erstellen von Karten mit Slices als Werten
m := make(map[string][]int)
Wenn Sie auf einen nicht vorhandenen Schlüssel zugreifen, wird ein Nullwert als Wert zurückgegeben. Da keine Slices wie Slices mit einer Länge von null funktionieren, müssen sie normalerweise nicht mit append
oder anderen integrierten Funktionen verwendet werden. append
müssen Sie normalerweise nicht prüfen, ob ein Schlüssel vorhanden ist:
// m["key1"] == nil && len(m["key1"]) == 0
m["key1"] = append(m["key1"], 1)
// len(m["key1"]) == 1
Durch das Löschen eines Schlüssels aus der Karte wird der Schlüssel auf ein Nullteil zurückgesetzt:
delete(m, "key1")
// m["key1"] == nil
Überprüfen Sie das Element in einer Karte
Um einen Wert aus der Karte zu erhalten, müssen Sie nur Folgendes tun: 00
value := mapName[ key ]
Wenn die Karte den Schlüssel enthält, wird der entsprechende Wert zurückgegeben.
Wenn nicht, wird ein Nullwert des Wertetyps der Map zurückgegeben (" 0
""
wenn ""
int
-Werte vorhanden sind, ""
wenn ""
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
Um zwischen leeren Werten und nicht vorhandenen Schlüsseln zu unterscheiden, können Sie den zweiten zurückgegebenen Wert des value, hasKey := map["key"]
(mit value, hasKey := map["key"]
).
Dieser zweite Wert ist vom boolean
und lautet:
-
true
wenn sich der Wert in der Karte befindet, -
false
wenn die Karte den angegebenen Schlüssel nicht enthält.
Sehen Sie sich folgendes Beispiel an:
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
}
Die Werte einer Karte wiederholen
people := map[string]int{
"john": 30,
"jane": 29,
"mark": 11,
}
for _, value := range people {
fmt.Println("Age:", value)
}
Beachten Sie, dass beim Durchlaufen einer Karte mit einer Bereichsschleife die Iterationsreihenfolge nicht angegeben wird und nicht von einer Iteration zur nächsten garantiert ist.
Kopieren Sie eine Karte
Karten enthalten wie Slices Verweise auf eine zugrunde liegende Datenstruktur. Wenn Sie also den Wert einer anderen Variablen zuweisen, wird nur die Referenz übergeben. Um die Karte zu kopieren, müssen Sie eine andere Karte erstellen und jeden Wert kopieren:
// 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
}
Eine Karte als Set verwenden
Einige Sprachen haben eine native Struktur für Mengen. Um einen Satz in Go zu erstellen, empfiehlt es sich, eine Zuordnung vom Werttyp des Satzes zu einer leeren Struktur ( map[Type]struct{}
) zu verwenden.
Zum Beispiel mit Strings:
// 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")
}