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

Lesen Sie den zugrunde liegenden Quellcode von Golang Slice

藏色散人
Freigeben: 2021-03-03 15:51:36
nach vorne
2981 Leute haben es durchsucht

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)
    Nach dem Login kopieren
  • 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}
Nach dem Login kopieren

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)}
Nach dem Login kopieren

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 < old.cap {
        panic(errorString("growslice: cap out of range"))
    }
    // 如果当前切片的大小为0,还调用了扩容方法,那么就新生成一个新的容量的切片返回
    // []struct{}
    if et.size == 0 {
        return slice{unsafe.Pointer(&zerobase), old.len, cap}
    }

    newcap := old.cap
    doublecap := newcap + newcap    //要扩容的容量大于2 *oldcap 新切片容量 = 该容量
    if cap > doublecap {
        newcap = cap
    } else {
    // 旧容量 小于1024,新容量= 旧容量 * 2 也就是扩容1倍
        if old.cap < 1024 {
            newcap = doublecap        } else {
            // 扩容容量 = 旧容量 +旧容量*1/4
            for 0 < newcap && newcap < cap {
                newcap += newcap / 4
            }
            //溢出之后 新容量=要扩容的容量
            if newcap <= 0 {
                newcap = cap
            }
        }
    }

    var overflow bool
    // 计算新的切片的容量,长度。
    var lenmem, newlenmem, capmem uintptr

    ....

    var p unsafe.Pointer    if et.ptrdata == 0 {
        p = mallocgc(capmem, nil, false)
        memclrNoHeapPointers(add(p, newlenmem), capmem-newlenmem)
    } else {
        p = mallocgc(capmem, et, true)
        if lenmem > 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}}
Nach dem Login kopieren

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
    Nach dem Login kopieren
  • 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!

Verwandte Etiketten:
Quelle:learnku.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