Maison >développement back-end >Golang >À propos de l'extension de Golang Slice

À propos de l'extension de Golang Slice

藏色散人
藏色散人avant
2021-06-23 16:17:561748parcourir
Chaque opération d'ajout vérifiera si la tranche a une capacité suffisante. Si cela est suffisant, les éléments seront ajoutés directement au tableau d'origine. et une nouvelle tranche sera renvoyée. Le tableau sous-jacent reste inchangé
et si la capacité n'est pas suffisante, un nouveau tableau sous-jacent avec une capacité suffisante sera créé. Les éléments du tableau précédent seront copiés en premier, puis les nouveaux éléments. sera ajouté à l'arrière, puis une nouvelle tranche sera renvoyée. Le tableau sous-jacent changera
La définition de capacité du nouveau tableau ici est d'augmenter selon le mécanisme de 乘以2

Recommandé. tutoriels associés : "tutoriel Golang"

Et aujourd'hui, j'ai vu En ce qui concerne la structure sous-jacente du découpage Golang, à savoir Reflect.SliceHeader, nous constatons que l'expansion d'append est pas exactement une multiplication par 2. Le code source est le suivant (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
}

First Append détermine si le type est slice, puis appelle grow Expansion, à partir du jugement de l1 <= m, nous pouvons constater que lorsque la capacité est effectivement suffisante, nous créons simplement une nouvelle tranche

pour le tableau d'origine. Mais lorsque la capacité est insuffisante, nous ne pouvons le voir que lorsque l'élément actuel i0 est inférieur à. 1024 Lorsque la vitesse est 2 fois, c'est normal. Sinon, elle n'augmente que de 25% à chaque fois. La vérification du code est la suivante :

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

Après que la capacité initiale ait atteint 1024, elle n'a augmenté que de 256.

func main() {
    str := make([]int, 1024)
    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))
}
输出:
1024 1024
1025 1280
1026 1280

Bien sûr ici Une autre confusion est que lorsque la capacité initiale est de 1023, ce n'est pas 1023×2, mais directement 1024×2. Lors du test de l'extension initiale 500, c'est aussi directement 512×2. est supposé que le niveau inférieur sera toujours complété à 2 lors de l'ajustement dynamique nième puissance, actuellement nous ne voyons que la définition de l'ajout sous le package intégré, et nous devons continuer à explorer

.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer