>  기사  >  백엔드 개발  >  Golang Slice의 추가 확장에 대해

Golang Slice의 추가 확장에 대해

藏色散人
藏色散人앞으로
2021-06-23 16:17:561685검색
모든 추가 작업은 슬라이스에 충분한 용량이 있는지 확인합니다. 용량이 충분하면 요소가 원래 배열에 직접 추가되고 새 슬라이스가 반환됩니다. 기본 배열은 그대로 유지됩니다
그리고 용량이 충분하지 않으면 용량이 충분한 새 기본 배열이 생성됩니다. 먼저 이전 배열의 요소를 복사하고 새 요소를 뒤에 추가한 다음 새 요소를 반환합니다. 기본 배열이 변경되고
여기서 새 배열의 용량 정의는 다음과 같습니다. 乘以2 메커니즘이 증가합니다

추천 관련 튜토리얼: "golang 튜토리얼"

Golang 슬라이싱의 기본 구조를 봤을 때, Reflect.SliceHeader는 오늘,append의 확장이 정확히 2배 증가가 아니라는 것을 발견했습니다. 소스 코드는 다음과 같습니다(Go 버전 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
}

먼저 Append가 유형이 슬라이스인지 여부를 판별한 다음, 용량을 확장하기 위해 호출이 증가합니다. l1

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

초기 용량이 1024에 도달한 후에만 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

물론 여기에는 또 다른 의문점이 있습니다. 초기 용량이 1023×2가 아니라 직접 1024×2로 초기 500 확장을 테스트해보면 바로 512×2입니다. 낮은 레벨은 동적으로 조정되는 것으로 추측됩니다. 항상 2의 n제곱에 추가됩니다. 현재는 내장 패키지 아래에 추가 정의만 표시되며 계속해서 살펴봐야 합니다

위 내용은 Golang Slice의 추가 확장에 대해의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제