2013-06-24 4 views
2

이동 중에 초기화되지 않은 slice을 할당하는 방법이 있습니까? 빈번한 패턴은 주어진 크기의 슬라이스를 버퍼로 생성 한 다음 그 중 일부만 receive 데이터에 사용하는 것입니다. spec 그것이 할당에 대한 배열을 초기화 기본값으로 상태로 버퍼를 많이가 할당 될 때이 초기화를 추가 할 수 있습니다초기화되지 않은 슬라이스 할당

b := make([]byte, 0x20000) // b is zero initialized 
n, err := conn.Read(b) 
// do stuff with b[:n]. all of b is zeroed for no reason 

예를 들면 다음과 같습니다.

답변

0

기술적으로 당신은 바 런타임과 unsafe.Pointer을 사용하여 메모리를 할당 할 수 있습니다. 그러나 이것은 틀린 일입니다.

더 나은 솔루션은 할당 횟수를 줄이는 것입니다. 버퍼를 루프 바깥으로 이동하거나 goroutine 버퍼가 필요한 경우 풀에 여러 버퍼를 할당하고 필요할 때마다 할당하십시오.

type BufferPool struct { 
    Capacity int 
    buffersize int 
    buffers []byte 
    lock sync.Mutex 
} 

func NewBufferPool(buffersize int, cap int) { 
    ret := new(BufferPool) 
    ret.Capacity = cap 
    ret.buffersize = buffersize 
    return ret 
} 

func (b *BufferPool) Alloc() []byte { 
    b.lock.Lock() 
    defer b.lock.Unlock() 
    if len(b.buffers) == 0 { 
     return make([]byte, b.buffersize) 
    } else { 
     ret := b.buffers[len(b.buffers) - 1] 
     b.buffers = b.buffers[0:len(b.buffers) - 1] 
     return ret 
    } 
} 

func (b *BufferPool) Free(buf []byte) { 
    if len(buf) != b.buffersize { 
     panic("illegal free") 
    } 
    b.lock.Lock() 
    defer b.lock.Unlock() 
    if len(b.buffers) < b.Capacity { 
     b.buffers = append(b.buffers, buf) 
    } 
} 
+0

또한이 예에서 버퍼에서 Free를 호출하는 것을 잊어 버리면 가비지 수집이되고 풀에 다시 추가되지 않고 누출되지 않습니다. – cthom06

+0

해제 된 버퍼를 저장하기 위해 버퍼링 된 채널을 사용해야합니까? –

+0

@MattJoiner 대신 그렇게 할 수는 있지만 버퍼링 된 아이템 수를 안전하게 확인하려면 잠금 장치가 필요합니다. 그러면 두 번 잠그거나 길이를 확인하지 않고 goroutines이 누출 될 것입니다. 항상 (peak_use - 수용량) goroutines가 채널을 밀기를 기다리고 있습니다. – cthom06

2

당신은 비는 bufs.Cache.Get에서 바이트 버퍼를 제로 수 (또는 동시 안전한 버전 CCache 참조) 할 수 있습니다.

참고 : 다음 docs에서 을 보장 할 수 없습니다하기에 의해 반환 된 버퍼 제로한다. 예를 들어 괜찮습니다. 버퍼를 io.Reader에 건네줍니다. 0으로 채워진 버퍼가 필요한 경우에는 Cget을 사용하십시오.