2017-02-13 12 views
1

Я новичок в Go и попытаюсь понять язык, чтобы написать эффективный код. В следующем коде размеры двух массивов различаются на 140%, может кто-нибудь объяснить это?Различные размеры массивов с использованием make или инициализации по умолчанию

package main 

import (
    "fmt" 
    "unsafe" 
) 

func main() { 
    ind1 := make([]bool, 10) 
    var ind2 [10]bool 
    fmt.Println(unsafe.Sizeof(ind1)) // 24 
    fmt.Println(len(ind1)) // 10 
    fmt.Println(unsafe.Sizeof(ind2)) // 10 
    fmt.Println(len(ind2)) // 10 
} 

Размер первого массива остается 10, даже в случае, если емкость установлена ​​в явном виде:

ind1 := make([]bool, 10, 10) 

Может кто-нибудь объяснить это? Есть ли дополнительные накладные расходы при использовании make? Если да, то почему рекомендуется использовать make over default initialization?

+1

Первое, когда обучение Go является работа через Тур Go (https://tour.golang.org). Второе - сделать это снова. Третье - чтение Эффективного Go (https://golang.org/doc/effective_go.html). Четвертое - чтение Spec (https://golang.org/ref/spec). Затем вы повторите тур, а затем вы беспокоитесь об эффективном коде. Не ранее :-) – Volker

ответ

5

Arrays и slices в Go - это разные вещи.

Ваш ind1 - это фрагмент, а ind2 - это массив. Длина массива является частью типа, поэтому, например, [2]bool и [3]bool - это 2 разных типа массива.

Врезка в Go является дескриптором для смежного сегмента базового массива и обеспечивает доступ к пронумерованной последовательности элементов из этого массива. Этот заголовок секции является структура типа структуры данных представлена ​​по типу reflect.SliceHeader:

type SliceHeader struct { 
     Data uintptr 
     Len int 
     Cap int 
} 

Он содержит указатель данных (к первому элементу, представленному сегмент), длина и емкость.

Функция unsafe.SizeOf() возвращает размер в байтах гипотетической переменной, как если бы она удерживала переданное значение. В него не включена никакая память, на которую возможно ссылаться.

Так что, если вы передаете значение среза (ind1), он расскажет вам размер выше среза заголовка. Обратите внимание, что размер полей SliceHeader зависит от архитектуры, например. int может быть 4 байта на одной платформе и может быть 8 байт на другой. Размер 24 применяется к 64-разрядным архитектурам.

The Go Playground работает на 32-битной архитектуре. Давайте посмотрим следующий пример:

fmt.Println(unsafe.Sizeof(make([]bool, 10))) 
fmt.Println(unsafe.Sizeof(make([]bool, 20))) 

fmt.Println(unsafe.Sizeof([10]bool{})) 
fmt.Println(unsafe.Sizeof([20]bool{})) 

Output (попробовать его на Go Playground):

12 
12 
10 
20 

Как вы можете видеть, независимо от длины среза вы передаете unsafe.SizeOf(), он всегда возвращается 12 на игровая площадка Go (и 24 на 64-битных архитектурах).

С другой стороны, значение массива включает в себя все его элементы и, как таковое, его размер зависит от его длины. Размер [10]bool составляет 10, и размер [20]bool 20.

См вопросы, связанные с + ответы, чтобы узнать больше о срезах, массивы и разности и отношения между ними:

How do I find the size of the array in go

Why have arrays in Go?

Why use arrays instead of slices?

Должностные обязанности читателей:

Go Slices: usage and internals

Arrays, slices (and strings): The mechanics of 'append'

1

ind1 - ломтик (тип []bool).

ind2 - массив (тип [10]bool).

Они не одного типа.

Результат unsafe.Sizeof(ind1), вероятно, не имеет ничего общего с аргументами, переданными make.