>백엔드 개발 >Golang >Golang의 `append()`가 채널을 통해 전송된 후 슬라이스를 수정하는 것처럼 보이는 이유는 무엇입니까?

Golang의 `append()`가 채널을 통해 전송된 후 슬라이스를 수정하는 것처럼 보이는 이유는 무엇입니까?

Linda Hamilton
Linda Hamilton원래의
2024-11-02 10:01:31352검색

Why Does Golang's `append()` Seem to Modify a Slice After It's Sent Over a Channel?

Golang의 add()는 언제 새 슬라이스를 생성합니까?

append()에 대한 문서에는 새 슬라이스를 할당하고 원본 슬라이스의 용량이 부족할 때 요소를 복사합니다. 그러나 부울 알파벳의 조합을 생성하는 다음 코드의 출력을 검토할 때 불일치가 발생합니다.

<code class="go">package main

import (
    "fmt"
)

func AddOption(c chan []bool, combo []bool, length int) {
    if length == 0 {
        fmt.Println(combo, "!")
        c <- combo
        return
    }
    var newCombo []bool
    for _, ch := range []bool{true, false} {
        newCombo = append(combo, ch)
        AddOption(c, newCombo, length-1)
    }
}

func main() {
    c := make(chan []bool)
    go func(c chan []bool) {
        defer close(c)
        AddOption(c, []bool{}, 4)
    }(c)
    for combination := range c {
        fmt.Println(combination)
    }
}</code>

대조 관찰

출력에서 느낌표로 끝나는 줄은 AddOption에 의해 채널을 통해 전송된 조각을 나타내고, 느낌표가 없는 줄은 main()에서 받은 조각을 나타냅니다. 눈에 띄게, Append()가 새로운 슬라이스를 반환한다고 주장함에도 불구하고 채널을 통해 전송된 슬라이스는 전송된 후 수정된 것으로 나타납니다.

소스 조사

의심스러운 코드 블록 is:

<code class="go">var newCombo []bool
for _, ch := range []bool{true, false} {
    newCombo = append(combo, ch)
    AddOption(c, newCombo, length-1)
}</code>

문서에 따르면 원래 슬라이스의 용량이 충분하지 않은 경우 추가()는 새로운 기본 데이터 배열을 가리키는 새 슬라이스 설명자를 반환해야 합니다. 그러나 AddOption의 두 번째 인수로 전달된 값은 슬라이스 설명자에 대한 포인터이거나 슬라이스 설명자의 실제 복사본일 수 있습니다.

동작 명확화

이 질문에 대한 대답은 슬라이스 데이터 유형과 실제 표현을 구별하는 데 있습니다. 슬라이스 설명자는 기본 데이터에 대한 포인터와 함께 길이 및 용량에 대한 두 개의 정수로 구성됩니다.

append()는 잠재적으로 다른 기본 데이터 배열을 사용하여 새 슬라이스 설명자를 반환하지만 데이터에 대한 포인터 용량을 늘리지 않는 한 동일하게 유지됩니다. 즉, 슬라이스 설명자 자체는 복사본이지만 포인터 값(기본 데이터에 대한 주소)은 공유됩니다.

추가 예

설명을 위해 다음을 고려하세요. 코드 조각:

<code class="go">package main

import "fmt"

func main() {
    s := make([]int, 0, 5)
    s = append(s, []int{1, 2, 3, 4}...)

    a := append(s, 5)
    fmt.Println(a)

    b := append(s, 6)
    fmt.Println(b)
    fmt.Println(a)
}</code>

이 코드는 다음을 인쇄합니다.

[1 2 3 4 5]
[1 2 3 4 6]
[1 2 3 4 6]

처음에는 s의 용량이 충분하므로 a와 b는 동일한 기본 데이터 포인터를 공유합니다. 그러나 s의 용량을 4로 줄이면 출력은 다음과 같이 변경됩니다.

[1 2 3 4 5]
[1 2 3 4 6]
[1 2 3 4 5]

이는 s의 용량이 충분할 때만 a와 b가 동일한 기본 데이터를 공유한다는 것을 보여줍니다.

위 내용은 Golang의 `append()`가 채널을 통해 전송된 후 슬라이스를 수정하는 것처럼 보이는 이유는 무엇입니까?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.