Как получить размер памяти переменной?
Кто-нибудь знает, как получить размер памяти переменной (int
, string
, []struct
и т.д.) и распечатать ее? Возможно ли это?
var i int = 1
//I want to get something like this:
fmt.Println("Size of i is: %?", i)
//Also, it would be nice if I could store the value into a string
Ответы
Ответ 1
Для этого вы можете использовать функцию unsafe.Sizeof.
Возвращает размер в байтах, занятый значением, которое вы передаете в него.
Вот рабочий пример:
package main
import "fmt"
import "unsafe"
func main() {
a := int(123)
b := int64(123)
c := "foo"
d := struct {
FieldA float32
FieldB string
}{0, "bar"}
fmt.Printf("a: %T, %d\n", a, unsafe.Sizeof(a))
fmt.Printf("b: %T, %d\n", b, unsafe.Sizeof(b))
fmt.Printf("c: %T, %d\n", c, unsafe.Sizeof(c))
fmt.Printf("d: %T, %d\n", d, unsafe.Sizeof(d))
}
Обратите внимание, что некоторые платформы явно запрещают использование небезопасных, потому что это.. ну, небезопасно. Это раньше включало AppEngine. Не уверен, что это так и сегодня, но я так себе представляю.
Как отмечает @Timur Fayzrakhmanov, reflect.TypeOf(variable).Size()
даст вам ту же информацию. Для пакета reflect
действует то же ограничение, что и для пакета unsafe
. Т.е.: некоторые платформы могут не разрешать его использование.
Ответ 2
Вы можете сделать это с помощью unsafe.Sizeof()
или reflect.Type.Size()
Ответ 3
Размер переменной можно определить с помощью unsafe.Sizeof(a)
. Результат останется неизменным для данного типа (т.е. int
, int64
, string
, struct
и т.д.), Независимо от его значения. Однако для типа string
вас может заинтересовать размер строки, которую ссылается переменной, и это определяется с помощью функции len(a)
для данной строки. Следующий фрагмент иллюстрирует, что размер переменной строки типа всегда равен 8, но длина строки, которая может ссылаться на переменные:
package main
import "fmt"
import "unsafe"
func main() {
s1 := "foo"
s2 := "foobar"
fmt.Printf("s1 size: %T, %d\n", s1, unsafe.Sizeof(s1))
fmt.Printf("s2 size: %T, %d\n", s2, unsafe.Sizeof(s2))
fmt.Printf("s1 len: %T, %d\n", s1, len(s1))
fmt.Printf("s2 len: %T, %d\n", s2, len(s2))
}
Вывод:
s1 size: string, 8
s2 size: string, 8
s1 len: string, 3
s2 len: string, 6
Последняя часть вашего вопроса касается назначения длины (то есть значения int
) в string
. Это можно сделать с помощью s := strconv.Itoa(i)
, где i
является переменной int
, а функция string
, возвращаемая функцией, назначается s
.
Примечание: имя функции преобразователя Itoa
, возможно короткая форма для Integer для ASCII. Большинство программистов Golang, вероятно, неправильно понимают имя функции как Iota
.
Ответ 4
От go/src/math/bits:
const uintSize = 32 << (^uint(0) >> 32 & 1) // 32 or 64
Я не тестировал его, но я ожидаю, что это будет быстрее, чем небезопасно. Sizeof().
BTW, так как член (^ uint (0) → 32 и 1) возвращает 0 на 32-битной дуге и 1 на 64-битной дуге, вы можете поместить любую мощность из двух значений слева от < оператор. Так что...
const uintSize = 4 << (^uint(0) >> 32 & 1) // 4 or 8
возвращает sizeof (uint) в байтах.
Ответ 5
unsafe.Sizeof() - правильное решение.
var i int
var u uint
var up uintptr
fmt.Printf("i Type:%T Size:%d\n", i, unsafe.Sizeof(i))
fmt.Printf("u Type:%T Size:%d\n", u, unsafe.Sizeof(u))
fmt.Printf("up Type:%T Size:%d\n", up, unsafe.Sizeof(up))
Типы int, uint и uintptr обычно имеют ширину 32 бита в 32-битных системах и 64 бита в 64-битных системах. Когда вам нужно целочисленное значение, вы должны использовать int, если у вас нет особых причин использовать целочисленный тип без размера или без знака.