web-dev-qa-db-de.com

So implementieren Sie skalierbare Arrays in Go

Ich komme aus einem C++ - Hintergrund und bin es gewohnt, die std::vector-Klasse für Dinge wie diese zu verwenden .. _. Nehmen wir an, ich möchte ein dynamisches Array von diesen:

type a struct {
    b int
    c string
}

Was ist die Standardmethode dafür?

Ein Snippet wäre sehr nützlich  

48
user181351

Verwenden Sie das append() builtin

Beispiel:

type mytype struct {
  a, b int
}

func main() {
  a := []mytype{mytype{1, 2}, mytype{3, 4}}
  a = append(a, mytype{5, 6})
}

Weitere Informationen zum Anhängen finden Sie in der Datei spec .

50
cthom06

Ein Go-Slice enthält drei Elemente: Daten, Länge und Kapazität.

s := make([]int, 0, 10)

Die Variable s ist ein Slice von Ints mit einer Länge von 0 und einer Kapazität von 10. Mit den integrierten Funktionen len () und cap () können Sie die Länge und Kapazität eines Slice ermitteln:

len(s) == 0
cap(s) == 10

Um die Länge eines Schnitts zu verlängern, einfach erneut schneiden:

s = s[0:5]
// len(s) == 5
// cap(s) == 10

Um die Länge zu verkürzen, können Sie einen Teilabschnitt nehmen:

s = s[0:1]
// len(s) == 1

Es gibt einige kürzere Möglichkeiten, make () aufzurufen:

a := make([]int, 10) 
// len(a) == cap(a) == 10

b := make([]int)
// len(b) == cap(b) == 0

Das ist alles gut und gut, aber was ist, wenn Sie die Länge einer Scheibe über ihre Kapazität hinaus verlängern müssen? Dazu müssen Sie ein neues Slice zuweisen und den Inhalt des alten Slice in das neue Slice kopieren. (Die Funktion "Kopieren" ist eine weitere integrierte Funktion.)

t := make([]int, len(s), 20)
copy(t, s)

Das Effective Go-Dokument führt dieses Beispiel etwas weiter aus, indem eine Append-Funktion implementiert wird, die ein Slice an ein anderes anhängt und gegebenenfalls deren Größe ändert.

Slices werden durch Arrays gesichert. Wenn Sie () ein Segment mit einer bestimmten Kapazität erstellen, wird ein Array dieser Kapazität im Hintergrund zugewiesen. Das Slice wird effektiv zu einem "intelligenten Zeiger" für dieses Array. Wenn Sie dieses Slice (oder ein Subslice dieses Slice) an eine andere Funktion übergeben, wird es als Zeiger auf dasselbe Array übergeben. Dies macht die Erstellung von Sub-Slices sehr kostengünstig - die Zuweisung des Backing-Arrays ist teuer.

Die Go-Standardbibliothek enthält eine Reihe von Containerpaketen - zum Beispiel vector -, mit denen die manuelle Verwaltung von Slices entfällt. Verwenden Sie Slices für die Geschwindigkeit und aufwändigere Containerklassen. (Wenn ich das sage, verwende ich immer noch Scheiben für die meisten Dinge.)

Sie fragen sich vielleicht, warum Sie all diese Mühe machen müssen. Schließlich bieten viele Sprachen Arrays mit dynamischer Größe als Grundelemente. Der Grund dafür ist an Goos Philosophie gebunden. Die Sprachdesigner gehen nicht davon aus, zu wissen, welche Zuweisungsrichtlinie für Ihr Programm geeignet ist. Stattdessen erhalten Sie die Tools, die Sie zum Erstellen eigener Datenstrukturen benötigen.

54
Andrew Gerrand

Der idiomatische Weg, dies zu tun, hat sich geändert .. Die Addition der integrierten append () - Funktion bedeutet, dass Sie ein Slice wie folgt erweitern können:

type a struct {
    b int
    c string
}

func main(){
    var mySlice []a
    mySlice = append(mySlice,a{5,"pizza"})
}

Append () fügt das angegebene Element an das Slice an, wenn Platz vorhanden ist, oder erweitert das Slice, wenn es nicht groß genug ist.

Weitere Informationen zu append () finden Sie hier http://golang.org/doc/go_spec.html#Appending_and_copying_slices

17
Jessta

sie könnten sich auch mit einem Slice begnügen. Dies ist ein Array, das seine aktuelle Länge kennt. Und kann eine separate Stromlänge und maximale Kapazität haben. Beachten Sie, dass die übergebenen Werte für Anfangsgröße und -kapazität nicht Konstanten sein müssen. Sie können also eine Funktion erstellen, die basierend auf ihren Parametern Schichten unterschiedlicher Länge erstellt und zurückgibt.

Der Nachteil ist, dass ein Slice [] Int einfach wie ein Array indiziert werden kann und bei dessen Verwendung Ints zurückgibt.

Der Nachteil ist, dass es nicht automatisch um die angegebene Kapazität wächst. Effective Go hat ein Beispiel, wie Sie mit der Neuzuordnung umgehen würden. 

der code wäre

type mytype struct {
   a, b int
}




func main() {

  sl := make([]mytype, 10, 50) //slice of 10 items, max capacity 50 these do not have to be constant expressions.
  sl[0] = mytype{1,2}
   //...
  for i, value := range sl {
  // ... do stuff with value
  }
}
1
user414731

Hallo, wir können dies auf zwei Arten tun

type mytype struct {
  a, b int
}

Mach es einfach so

  1. Ohne anhängen

__

a := []mytype{mytype{1, 2}, mytype{3, 4}, mytype{4, 5}}
  1. Mit anhängen

__

a:=  append([]mytype{}, mytype{1, 2}, mytype{3, 4}, mytype{4, 5})

Fügen Sie so viel hinzu, wie Sie möchten. Der erste ist eine einfache Möglichkeit, dies zu tun. Hoffe, das wird dir helfen.

0
amku91