Es gibt keinen prägnanteren Weg, was Sie getan haben, ist der "richtige" Weg; weil Scheiben immer eindimensional sind, aber zusammengesetzt werden können, um höherdimensionale Objekte zu konstruieren. Sehen Sie diese Frage für weitere Informationen: Go: Wie ist zwei Speicher Darstellung der dreidimensionalen Anordnung .
Eine Sache, die Sie vereinfachen können, ist die Verwendung des for range
Konstrukts:
a := make([][]uint8, dy)
for i := range a {
a[i] = make([]uint8, dx)
}
Beachten Sie auch, dass Sie, wenn Sie Ihr Slice mit einem zusammengesetzten Literal initialisieren , dieses kostenlos erhalten, zum Beispiel:
a := [][]uint8{
{0, 1, 2, 3},
{4, 5, 6, 7},
}
fmt.Println(a) // Output is [[0 1 2 3] [4 5 6 7]]
Ja, dies hat seine Grenzen, da Sie anscheinend alle Elemente aufzählen müssen. Es gibt jedoch einige Tricks, nämlich, dass Sie nicht alle Werte aufzählen müssen, sondern nur diejenigen, die nicht die Nullwerte des Elementtyps des Slice sind. Weitere Informationen hierzu finden Sie unter Schlüsselelemente in der Initialisierung des Golang-Arrays .
Wenn Sie beispielsweise ein Slice möchten, in dem die ersten 10 Elemente Nullen sind, und dann folgt 1
und 2
, kann es wie folgt erstellt werden:
b := []uint{10: 1, 2}
fmt.Println(b) // Prints [0 0 0 0 0 0 0 0 0 0 1 2]
Beachten Sie auch, dass Arrays anstelle von Slices sehr einfach erstellt werden können:
c := [5][5]uint8{}
fmt.Println(c)
Ausgabe ist:
[[0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0] [0 0 0 0 0]]
Bei Arrays müssen Sie nicht über das "äußere" Array iterieren und "innere" Arrays initialisieren, da Arrays keine Deskriptoren, sondern Werte sind. Weitere Informationen finden Sie im Blog-Beitrag Arrays, Slices (und Strings): Die Mechanik des Anhängens .
Probieren Sie die Beispiele auf dem Go Playground aus .
cannot use [5][2]string literal (type [5][2]string) as type [][]string in field value
wenn ich versuche, das Array dem zuzuweisen, was ich denke, dass Go ein Slice ist.Es gibt zwei Möglichkeiten, Slices zum Erstellen einer Matrix zu verwenden. Schauen wir uns die Unterschiede zwischen ihnen an.
Erste Methode:
Zweite Methode:
In Bezug auf die erste Methode stellt das Tätigen aufeinanderfolgender
make
Aufrufe nicht sicher, dass Sie eine zusammenhängende Matrix erhalten, sodass die Matrix möglicherweise im Speicher aufgeteilt ist. Stellen wir uns ein Beispiel mit zwei Go-Routinen vor, die dies verursachen könnten:make([][]int, n)
, um den zugewiesenen Speichermatrix
abzurufen, wobei ein Speicherelement von 0x000 bis 0x07F abgerufen wird.make([]int, m)
, wobei von 0x080 bis 0x0FF gewechselt wird.make
(für seine eigenen Zwecke) und erhält von 0x100 bis 0x17F (direkt neben der ersten Zeile der Routine # 0).make([]int, m)
der zweiten Schleife entsprechende Iteration durch und erhält für die zweite Zeile 0x180 bis 0x1FF. Zu diesem Zeitpunkt haben wir bereits zwei geteilte Zeilen.Bei der zweiten Methode versucht die Routine
make([]int, n*m)
, die gesamte Matrix in einem einzigen Slice zuzuordnen, um die Kontiguität sicherzustellen. Danach wird eine Schleife benötigt, um die Matrixzeiger auf die Unterzeilen zu aktualisieren, die jeder Zeile entsprechen.Sie können mit dem oben auf dem Go Playground gezeigten Code spielen , um den Unterschied im zugewiesenen Speicher mit beiden Methoden zu sehen. Beachten Sie, dass ich
runtime.Gosched()
nur verwendet habe, um den Prozessor zu erhalten und den Scheduler zu zwingen, zu einer anderen Routine zu wechseln.Welches verwenden? Stellen Sie sich den schlimmsten Fall mit der ersten Methode vor, dh jede Zeile befindet sich nicht neben einer anderen Zeile im Speicher. Wenn Ihr Programm dann die Matrixelemente durchläuft (um sie zu lesen oder zu schreiben), treten im Vergleich zur zweiten Methode aufgrund der schlechteren Datenlokalität wahrscheinlich mehr Cache-Fehler (daher eine höhere Latenz) auf. Andererseits ist es mit der zweiten Methode aufgrund der Speicherfragmentierung (über den gesamten Speicher verteilte Blöcke) möglicherweise nicht möglich, ein einzelnes Stück Speicher für die Matrix zuzuweisen, obwohl theoretisch möglicherweise genügend freier Speicher dafür vorhanden ist .
Daher sollten Sie immer die zweite Methode verwenden, um die Datenlokalität zu nutzen, es sei denn, es gibt viel Speicherfragmentierung und die zuzuordnende Matrix ist groß genug.
quelle
In früheren Antworten haben wir die Situation nicht berücksichtigt, in der die anfängliche Länge unbekannt ist. In diesem Fall können Sie die folgende Logik verwenden, um eine Matrix zu erstellen
https://play.golang.org/p/pHgggHr4nbB
quelle