2017-11-03 1 views
0

최근에 학습을 해본 결과 재 할당이 발생할 때 슬라이스 동작에 대한 질문이있었습니다. 나는 같은 구조체에 대한 포인터의 슬라이스가 가정 : 나는 다른 기능이 조각을 통과했고, 나의 이해는 내부적으로는 실행 값으로 슬라이스 헤더를 전달하는 경우골란 슬라이스 추가 및 재 할당

var a []*A 

별도의 goroutine을 사용하여 슬라이스에서 읽는 반면, goroutine을 시작한 함수는 슬라이스에 계속 추가됩니다. 예를 들어 슬라이스 헤더의 사본과 함께 자신의 goroutine에서 실행되는 나의 이해에서 그래서

package main 

type A struct { 
    foo int 
} 

func main() { 
    a := make([]*A, 0, 100) 
    ch := make(chan int) 
    for i := 0; i < 100; i++ { 
    a = append(a, &A{i}) 
    } 
    go read_slice(a, ch) 
    for i := 0; i < 100; i++ { 
    a = append(a, &A{i+100}) 
    } 
    <-ch 
} 

func read_slice(a []*A, ch chan int) { 
    for i := range a { 
    fmt.Printf("%d ", a[i].foo) 
    } 
    ch <- 1 
} 

의 read_slice() 함수로, 현재의 보조 배열에 대한 기본 포인터와의 크기가 그것이 내가 foo에 접근 할 수 있도록 호출 된 시간.

그러나 다른 goroutine이 슬라이스에 추가되면 용량을 초과 할 때 재 할당을 트리거합니다. go 런타임은 read_slice()에서 사용중인 이전 배킹 배열에 메모리를 할당 해제하지 않습니다. 그 함수에 참조가 있으므로?

"run -race slice.go"로 실행 해 보았지만 아무 것도보고하지 못했지만 여기서 뭔가 잘못하고있는 것 같습니까? 모든 포인터는 감사하겠습니다.

감사합니다.

답변

3

백킹 어레이에 대한 참조가 없을 때까지 GC는 백킹 어레이를 수집하지 않습니다. 프로그램에는 종족이 없습니다.

없이 goroutines과 같은 경우를 생각해

a := make([]*A, 0, 100) 
    for i := 0; i < 100; i++ { 
    a = append(a, &A{i}) 
    } 
    b := a 
    for i := 0; i < 100; i++ { 
    b = append(b, &A{i+100}) 
    } 

ab에 추가 될 때 상기 제 100 포인터 백킹 배열을 참조하는 것 슬라이스는 새로운 보조 배열을 할당한다. 슬라이스 a에는지지 배열에 매달린 참조가 없습니다.

지금 시나리오에 goroutine을 추가

a := make([]*A, 0, 100) 
    for i := 0; i < 100; i++ { 
    a = append(a, &A{i}) 
    } 
    b := a 
    go read_slice(a, ch) 
    for i := 0; i < 100; i++ { 
    b = append(b, &A{i+100}) 
    } 

goroutine 행복 슬라이스 a를 사용할 수 있습니다. 매달린 참조가 없습니다.

이제 해당 프로그램을 고려해보십시오. 마지막 스 니펫과 기능적으로 동일합니다.

+0

빠른 응답을 보내 주셔서 감사합니다. – muddy