2017-09-21 2 views
5

코드의 성능에 민감한 몇 가지 섹션에서 할당을 줄이기 위해 버퍼 풀을 사용하는 프로그램이 있습니다. 이 같은슬라이스를 '용량으로 확장하는 가장 간단한 방법은 무엇입니까?

뭔가 : play link

// some file or any data source 
var r io.Reader = bytes.NewReader([]byte{1,2,3}) 

// initialize slice to max expected capacity 
dat := make([]byte, 20) 

// read some data into it. Trim to length. 
n, err := r.Read(dat) 
handle(err) 
dat = dat[:n] 

// now I want to reuse it: 
for len(dat) < cap(dat) { 
     dat = append(dat, 0) 
} 

log.Println(len(dat)) 
// add it to free list for reuse later 
// bufferPool.Put(dat) 

난 항상 고정 할당 길이 조각, 필요한 최대 크기보다 큰 보장됩니다. 버퍼를 사용하려면 실제 데이터 길이로 크기를 줄여야하지만 다음 번에 필요할 때 다시 읽으려면 최대 크기 여야합니다.

내가 슬라이스를 확장하는 방법을 알고있는 유일한 방법은 append입니다. 그래서 사용하고있는 것입니다. 루프는 비록 더러운 슈퍼를 느낀다. 잠재적으로 비효율적입니다. 내 벤치마킹은 끔찍하지 않다는 것을 보여 주지만 더 나은 방법이 있어야한다고 생각합니다.

슬라이스의 내부 표현에 대해서만 알고 있지만, 실제로 데이터를 추가하지 않고도 길이 값을 어떻게 든 재정의 할 수 있다면 정말 좋을 것입니다. 나는 그것을 제로로 할 필요가 없습니다.

더 좋은 방법이 있나요?

답변

7

슬라이스의 용량을 "확장"하는 것은 단순히 slice expression이며 용량을 높은 인덱스로 지정합니다. 높은 지수는 길이보다 작을 필요는 없습니다. 제한은 다음과 같습니다.

배열 또는 문자열의 경우 색인은 0 <= low <= high <= len(a) 인 경우 범위 내에 있고 그렇지 않으면 범위를 벗어납니다. 조각의 경우, 위쪽 색인 바운드는 길이가 아닌 cap(a)입니다.

예 :

b := make([]byte, 10, 20) 
fmt.Println(len(b), cap(b), b) 

b = b[:cap(b)] 
fmt.Println(len(b), cap(b), b) 

출력합니다 (Go Playground에 그것을 시도) : 당신은 슬라이스와 용량에 조각을 확장 할 수 있습니다

10 20 [0 0 0 0 0 0 0 0 0 0] 
20 20 [0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0] 
+0

와우, 나는 지금 어리 석다. 나는 그것을 시험해보고 한계를 벗어나 맹세했다. 그러나 당신이 그 역량을 유지하는 한 그것은 정말로 효과가 있습니다. – captncraig

관련 문제