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")
}


Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow