2014-12-25 4 views
7

Ho il seguente codice in esecuzione in un sistema operativo Linux a 64-bit in una macchina 4Gb:Lunghezza massima di una fetta di Go

package main 

import (
    "fmt" 
    "math" 
) 

func main() { 
    r := make([]bool, math.MaxInt32) 

    fmt.Println("Size: ", len(r)) 
} 

Quando eseguo questo ottengo:

Size: 2147483647 

Se cambio la math.MaxInt32 per math.MaxUint32 ottengo:

fatal error: runtime: out of memory 

Con dimensioni fetta di math.MaxUint32 mi sono imbattuto dalla memoria, mi aspettavo che, ma quando provo utilizza math.MaxInt64 ottengo:

panic: runtime error: makeslice: len out of range 

Quindi verrà aggiustata non posso creare una sezione con una dimensione di math.MaxInt64, che ci portano alla mia domanda: Se la memoria non è un problema, qual è la fetta più grande che non riesco a creare in Go?

Mi ricordo che, in Java, indici di matrice prime sono gestite con il tipo int, quindi la dimensione massima di un array di grezzo è il valore massimo di un int, se si tenta di farlo con long intende sollevare un'eccezione (per quanto mi ricordo), è lo stesso con Go? l'indice di sezione è associato a un tipo specifico?

EDIT:

ho eseguito il test utilizzando struct{} invece di bool e l'assegnazione math.MaxInt64 elementi. Tutto è andato come previsto, e le stampe:

Size: 9223372036854775807 

Quindi, un'altra domanda, perché ci sono due messaggi di errore differenti quando sembra che l'errore è lo stesso (memoria insufficiente)?

Quali sono le condizioni per l'apertura di ciascun errore?

+0

Così sembra che si tratta di una questione di messaggio di errore di ambiguità, niente di più ... :) –

risposta

10

Secondo i documenti, The elements can be addressed by integer indices 0 through len(s)-1. Ciò significa che la capacità massima per una sezione è la dimensione del numero intero predefinito sulla build di destinazione.

EDIT: Guardando il codice sorgente, sembra che ci sia un controllo di sicurezza per assicurarsi che questa dimensione della fetta è a tutto il possibile:

func makeslice(t *slicetype, len64 int64, cap64 int64) sliceStruct { 
    // NOTE: The len > MaxMem/elemsize check here is not strictly necessary, 
    // but it produces a 'len out of range' error instead of a 'cap out of range' error 
    // when someone does make([]T, bignumber). 'cap out of range' is true too, 
    // but since the cap is only being supplied implicitly, saying len is clearer. 
    // See issue 4085. 
    len := int(len64) 
    if len64 < 0 || int64(len) != len64 || t.elem.size > 0 && uintptr(len) > maxmem/uintptr(t.elem.size) { 
     panic(errorString("makeslice: len out of range")) 
    } 

Quindi in questo caso, sembra che uintptr(len) > maxmem/uintptr(t.elem.size) così non siamo autorizzati a fare questa dimensione di un'assegnazione.

Tuttavia quando ho allocare struct{} che prende alcun ricordo, questa dimensione è consentito:

func main(){ 
    r := make([]struct{}, math.MaxInt64) 
    fmt.Println(len(r)) 
} 
// prints 9223372036854775807 
+0

Sono sicuro che Corro 64 bit Go, se faccio 'go version' stampa' go versione go1.4 linux/amd64' –

+0

@ SimonOroño che cosa significa 'go env' print per GOARCH? –

+0

@ SimonOroño Ho visto il codice sorgente di Go e penso di conoscere il problema. Aggiornamento della mia risposta. –