Объявить константный массив


164

Я пытался:

const ascii = "abcdefghijklmnopqrstuvwxyz"
const letter_goodness []float32  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness  = { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }
const letter_goodness = []float32 { .0817,.0149,.0278,.0425,.1270,.0223,.0202, .0609,.0697,.0015,.0077,.0402,.0241,.0675, .0751,.0193,.0009,.0599,.0633,.0906,.0276, .0098,.0236,.0015,.0197,.0007 }

Во-первых, объявление и инициализация работают нормально, но второй, третий и четвертый не работают. Как я могу объявить и инициализировать массив const с плавающей точкой?

Ответы:


232

Массив не является неизменным по своей природе; Вы не можете сделать это постоянным.

Ближайшее, что вы можете получить:

var letter_goodness = [...]float32 {.0817, .0149, .0278, .0425, .1270, .0223, .0202, .0609, .0697, .0015, .0077, .0402, .0241, .0675, .0751, .0193, .0009, .0599, .0633, .0906, .0276, .0098, .0236, .0015, .0197, .0007 }

Обратите внимание: [...]вместо []: он гарантирует, что вы получите массив (фиксированный размер) вместо среза. Значения не фиксированные, а размер.


126
Просто для пояснения: [...]Tсинтаксис является сахаром для [123]T. Он создает массив фиксированного размера, но позволяет компилятору выяснить, сколько в нем элементов.
Джимт

5
Я предполагаю, что для разрешения постоянных массивов потребуются обновления системы типов. Иначе, если бы вы определили функцию, f(xs [5]int)вы бы не знали, был ли переданный массив постоянным или изменяемым.
Томас Ахле

tks, у меня есть проблемы, когда я пытаюсь cannot use constants.FilesRequired (type [4]string) as type []string in argument to strings.Join
Эдди Эрнандес

Спасибо за решение среза. Сомнение: сам массив неизменен, верно? Нельзя добавлять или удалять элементы после создания массива, нет? Я могу, однако, редактировать элементы массива.
legends2k

@ legends2k Вы не можете изменить размер массива, да, но вы можете поместить другие значения в его слоты.
Денис Сегюре

63

С Эффективного Go :

Константы в Го просто постоянны. Они создаются во время компиляции, даже если они определены как локальные в функциях, и могут быть только числами, строками или логическими значениями. Из-за ограничений во время компиляции определяющие их выражения должны быть константными выражениями, которые могут вычисляться компилятором. Например, 1 << 3 является константным выражением, в то время как math.Sin (math.Pi / 4) - не потому, что вызов функции math.Sin должен происходить во время выполнения.

Срезы и массивы всегда оцениваются во время выполнения:

var TestSlice = []float32 {.03, .02}
var TestArray = [2]float32 {.03, .02}
var TestArray2 = [...]float32 {.03, .02}

[...]говорит компилятору вычислить длину самого массива. Ломтики обертывают массивы и с ними легче работать в большинстве случаев. Вместо использования констант просто сделайте переменные недоступными для других пакетов, используя первую букву в нижнем регистре:

var ThisIsPublic = [2]float32 {.03, .02}
var thisIsPrivate = [2]float32 {.03, .02}

thisIsPrivateдоступно только в пакете, который он определил. Если вам нужен доступ для чтения извне, вы можете написать простую функцию получения (см. Раздел «Получение в golang» ).


12

В Go нет такого понятия, как константа массива.

Цитирование из спецификации языка Go: Константы :

Существуют логические константы , рунные константы , целочисленные константы , константы с плавающей точкой , комплексные константы и строковые константы . Рунические, целочисленные, с плавающей точкой и комплексные константы вместе называются числовыми константами .

Постоянное выражение (которое используется для инициализации константы) может содержать только постоянные операнды и вычисляется во время компиляции.

В спецификации перечислены различные типы констант. Обратите внимание, что вы можете создавать и инициализировать константы с помощью константных выражений типов, имеющих один из разрешенных типов в качестве базового типа . Например, это действительно:

func main() {
    type Myint int
    const i1 Myint = 1
    const i2 = Myint(2)
    fmt.Printf("%T %v\n", i1, i1)
    fmt.Printf("%T %v\n", i2, i2)
}

Вывод (попробуйте на Go Playground ):

main.Myint 1
main.Myint 2

Если вам нужен массив, он может быть только переменной, но не константой.

Я рекомендую эту замечательную статью в блоге о константах: Константы


тогда что делать, если нужен контейнер с постоянным размером?

@ Atomic_alarm Можете ли вы уточнить, пожалуйста?
icza

Существует ли в Голанге аналог C-массива?

@Atomic_alarm Да, массивы тоже существуют в Go, они просто не являются константными выражениями, они оцениваются во время выполнения. Таким образом, константа не может иметь тип массива, но переменная может. Например:var arr = [2]int{2, 3}
icza

3

Как уже упоминалось, для этого не существует официальной конструкции Go. Самое близкое, что я могу себе представить, - это функция, которая возвращает срез. Таким образом, вы можете гарантировать, что никто не будет манипулировать элементами исходного среза (так как он «жестко запрограммирован» в массиве).

Я сократил ваш кусок, чтобы сделать его ... короче ...

func GetLetterGoodness() []float32 {
    return [...]float32 { .0817,.0149,.0278,.0425,.1270,.0223 }
}

4
Похоже, это лучший способ, но тип возврата func не совпадает. cannot use [6]string literal (type [6]string) as type []string in return argumentтакreturn []float32 { ... }
theRemix

@theRemix Три возможных исправления: (1) удалить, ...чтобы объявить литерал среза вместо литерала массива. (2) измените тип возврата на [6]float32. (3) присвоить выражение переменной массива, a := [...]float32 { (etc.) }и возвращает срез всех элементов: return a[:]. (Литералы массива не адресуемы, я не понимаю, почему.)
Дэвид

Я не уверен, что ты имеешь в виду. Похоже, вы пытаетесь решить что-то в своем коде, что, вероятно, лучше решается с помощью (модульных) тестов.
Dynom
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.