Heim  >  Artikel  >  Backend-Entwicklung  >  Lesen Sie den zugrunde liegenden Quellcode von Golang Slice

Lesen Sie den zugrunde liegenden Quellcode von Golang Slice

藏色散人
藏色散人nach vorne
2021-03-03 15:51:362893Durchsuche

Array

Lesen Sie den zugrunde liegenden Quellcode von Golang Slice Bevor wir über das Slicing sprechen, sprechen wir über Arrays. Zwei Merkmale von Arrays

Eine kontinuierliche Speicheradresse, jedes Element ist kontinuierlich

Die Elemente sind vom gleichen Typ und die Anzahl der Elemente ist fest

    Go-Array ist ein Werttyp, der Zuweisungs- und Funktionsparameterübergabeoperationen durchführt Kopieren Sie die gesamten Array-Daten.
  • arr := [2]int{1,2}arr2 := arr
    fmt.Printf("%p %p",&arr ,&arr2)//切片slice1 := []int{1,2}slice2 := slice1
    fmt.Printf("%p %p",slice1 ,slice2)
  • Slice

Ein Slice ist eine Referenz auf ein kontinuierliches Fragment eines Arrays, also ist ein Slice ein Referenztyp. Ein Slice ist ein Array variabler Länge.

Die Datenstruktur von Slice ist wie folgt definiert: runtime/slice.go#L13

type slice struct {
    array unsafe.Pointer    len   int
    cap   int}

array ist die Adresse des zugrunde liegenden Arrays

len die Länge des Slice

cap die Kapazität des Slice
  • Slice erstellen
  • src /runtime/slice.go#L83
func makeslice(et *_type, len, cap int) unsafe.Pointer {
    mem, overflow := math.MulUintptr(et.size, uintptr(cap))
    ....
    return mallocgc(mem, et, true)}

Die Grundlogik besteht darin, ein Stück Speicher basierend auf der Kapazität zu beantragen.

Slice-Erweiterung

Kapazitätserweiterung liegt vor, wenn die Länge des Slice größer als die Kapazität ist und das zugrunde liegende Array nicht mehr hineinpasst

func growslice(et *_type, old slice, cap int) slice {
    ...
    // 如果新要扩容的容量比原来的容量还要小,直接报panic
    if cap 6fcbe6a181235a2d91480a84b8bdbb32 doublecap {
        newcap = cap
    } else {
    // 旧容量 小于1024,新容量= 旧容量 * 2 也就是扩容1倍
        if old.cap c9221202ba118f4c45c4e2fcde42ff0d 0 && writeBarrier.enabled {
            bulkBarrierPreWriteSrcOnly(uintptr(p), uintptr(old.array), lenmem-et.size+et.ptrdata)
        }
    }
    //移动到p
    memmove(p, old.array, lenmem)
    //返回slice结构,让slice.array指向p
    return slice{p, old.len, newcap}}

Neue Anwendungskapazitätsobergrenze, wenn sie größer als das Zweifache der alten Kapazität ist ( oldcap), die zu erweiternde Kapazität (newcap) = Neue Anwendungskapazitätsobergrenze

Wenn die alte Kapazität (oldcap) Wenn der Wert überläuft, ist die zu erweiternde Kapazität Kapazität = neu angewendete Kapazität
  •   arr := make([]int,1024)
      arr = append(arr,1)
      fmt.Println(len(arr),cap(arr))// 1025,1280
      arr1 := make([]int,10)
      arr1 = append(arr1,1)
      fmt.Println(len(arr1),cap(arr1))//11 20
  • Hinweise: Slices teilen sich das zugrunde liegende Array. Wenn also das Slice zugewiesen wird, wird das Slice geändert führt dazu, dass sich das zugrunde liegende Array ändert, was zu einem FEHLER führt

Das obige ist der detaillierte Inhalt vonLesen Sie den zugrunde liegenden Quellcode von Golang Slice. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:learnku.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen