Ce face unsafe.Sizeof
unsafe.Sizeof(x) spune câți octeți ocupă variabila x însăși. Valoarea este calculată la compilare (x nu este evaluat) și depinde de procesor: pe un sistem de 64 de biți, int și pointerii au 8 octeți.
Pentru tipurile care trimit spre alte date, rezultatul nu include acele date. Un string ocupă 16 octeți (pointer + lungime) oricât de lung ar fi textul, iar un slice 24 de octeți (pointer + lungime + capacitate), oricâte elemente ar avea.
La structuri, rezultatul include și octeții de umplutură (padding) adăugați ca fiecare câmp să fie aliniat. Ordinea câmpurilor poate schimba mărimea structurii. Funcțiile înrudite unsafe.Alignof și unsafe.Offsetof dau alinierea și poziția unui câmp. Pachetul unsafe ocolește siguranța tipurilor; Sizeof este însă inofensivă, doar citește o informație.
Parametri
| Parametru | Descriere |
|---|---|
x |
O expresie de orice tip; contează doar tipul ei. |
Ce returnează
Mărimea în octeți, ca uintptr.
Exemple
Exemplul 1: Mărimea tipurilor de bază
Rezultatul este pentru un sistem de 64 de biți. Textul lung și slice-ul cu un milion de elemente au aceeași mărime ca variantele scurte.
package main
import (
"fmt"
"strings"
"unsafe"
)
func main() {
var (
b bool
i8 int8
i int
f float64
p *int
s = "Iași"
lung = strings.Repeat("a", 1000)
sl = make([]int, 1_000_000)
m = map[string]int{}
)
fmt.Println("bool:", unsafe.Sizeof(b))
fmt.Println("int8:", unsafe.Sizeof(i8))
fmt.Println("int:", unsafe.Sizeof(i))
fmt.Println("float64:", unsafe.Sizeof(f))
fmt.Println("*int:", unsafe.Sizeof(p))
fmt.Println("string:", unsafe.Sizeof(s), unsafe.Sizeof(lung))
fmt.Println("[]int:", unsafe.Sizeof(sl))
fmt.Println("map:", unsafe.Sizeof(m))
}
Rezultat
bool: 1
int8: 1
int: 8
float64: 8
*int: 8
string: 16 16
[]int: 24
map: 8
Exemplul 2: Ordinea câmpurilor schimbă mărimea unei structuri
În prima structură, după fiecare bool se adaugă 7 octeți de umplutură ca int64 să înceapă la un multiplu de 8. Grupând câmpurile mici, structura scade de la 24 la 16 octeți.
package main
import (
"fmt"
"unsafe"
)
type Risipitor struct {
Activ bool
Sold int64
Admin bool
}
type Compact struct {
Sold int64
Activ bool
Admin bool
}
func main() {
fmt.Println("Risipitor:", unsafe.Sizeof(Risipitor{}))
fmt.Println("Compact: ", unsafe.Sizeof(Compact{}))
var r Risipitor
fmt.Println("Sold începe la octetul", unsafe.Offsetof(r.Sold), "cu alinierea", unsafe.Alignof(r.Sold))
}
Rezultat
Risipitor: 24
Compact: 16
Sold începe la octetul 8 cu alinierea 8
Greșeli frecvente
- Folosești
unsafe.Sizeofca să afli câtă memorie ocupă un slice sau un text cu tot cu conținut: primești doar mărimea antetului (24, respectiv 16 octeți). Pentru conținut calculezilen(s) * unsafe.Sizeof(s[0]), respectivlen(text). - Presupui aceleași valori pe toate sistemele: pe 32 de biți,
intși pointerii au 4 octeți.
Comenzi înrudite
math.Float64bits: Transformă un float64/float32 în biții lui IEEE 754 (uint64/uint32) și înapoi, fără nicio conversie a valorii.slices.Grow: Grow rezervă loc pentru încă n elemente fără realocări ulterioare; Clip elimină capacitatea nefolosită.