Über die Append-Erweiterung von Golang Slice

藏色散人
Freigeben: 2021-06-23 16:17:56
nach vorne
1698 Leute haben es durchsucht
Bei jedem Anhängevorgang wird überprüft, ob das Slice über genügend Kapazität verfügt. Wenn diese ausreicht, werden Elemente direkt an das ursprüngliche Array angehängt und ein neues Slice zurückgegeben. Das zugrunde liegende Array bleibt unverändert. Wenn die Kapazität nicht ausreicht, wird ein neues zugrunde liegendes Array mit ausreichender Kapazität erstellt. Kopieren Sie zunächst die Elemente des vorherigen Arrays, hängen Sie die neuen Elemente an die Rückseite an und geben Sie dann das neue zurück Das zugrunde liegende Array ändert sich und die Kapazitätsdefinition des neuen Arrays lautet wie folgt Heute habe ich bei Reflect.SliceHeader festgestellt, dass die Erweiterung von append nicht gerade eine Verdoppelung darstellt. Der Quellcode lautet wie folgt (Go-Version 1.13):
// grow grows the slice s so that it can hold extra more values, allocating
// more capacity if needed. It also returns the old and new slice lengths.
func grow(s Value, extra int) (Value, int, int) {
    i0 := s.Len()
    i1 := i0 + extra
    if i1 < i0 {
        panic("reflect.Append: slice overflow")
    }
    m := s.Cap()
    if i1 <= m {
        return s.Slice(0, i1), i0, i1
    }
    if m == 0 {
        m = extra
    } else {
        for m < i1 {
            if i0 < 1024 {
                m += m
            } else {
                m += m / 4
            }
        }
    }
    t := MakeSlice(s.Type(), i1, m)
    Copy(t, s)
    return t, i0, i1
}

// Append appends the values x to a slice s and returns the resulting slice.
// As in Go, each x's value must be assignable to the slice's element type.
func Append(s Value, x ...Value) Value {
    s.mustBe(Slice)
    s, i0, i1 := grow(s, len(x))
    for i, j := i0, 0; i < i1; i, j = i+1, j+1 {
        s.Index(i).Set(x[j])
    }
    return s
}
Nach dem Login kopieren

Zuerst bestimmt Append, ob der Typ Slice ist, und dann Aus der Beurteilung von l1 <= m lässt sich schließen, dass bei ausreichender Kapazität lediglich ein neues Slice für das ursprüngliche Array erstellt wird. Wenn die Kapazität jedoch nicht ausreicht, ist dies möglich Beachten Sie, dass die 2-fache Geschwindigkeit nur dann normal ist, wenn das aktuelle Element i0 kleiner als 1024 ist. Andernfalls erfolgt die Codeüberprüfung wie folgt: 乘以2
func main() {
    str := make([]int, 1023)
    fmt.Println(len(str), cap(str))
    str = append(str, 1)
    fmt.Println(len(str), cap(str))
    str = append(str, 1)
    fmt.Println(len(str), cap(str))
}

输出:
1023 1023
1024 2048
1025 2048
Nach dem Login kopieren
Nachdem die anfängliche Kapazität 1024 erreicht hat wächst 256

rrree Natürlich gibt es hier einen weiteren Zweifel. Wenn die anfängliche Kapazität 1023 × 2 beträgt, beträgt sie direkt 1024 × 2 Es wird vermutet, dass die untere Ebene dynamisch angepasst wird. Sie wird immer zur n-ten Potenz von 2 addiert. Derzeit sehen wir die Definition von „append“ nur unter dem integrierten Paket und müssen sie weiter untersuchen

Das obige ist der detaillierte Inhalt vonÜber die Append-Erweiterung von Golang Slice. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:segmentfault.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage