Оголосити постійний масив


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. Він створює масив фіксованого розміру, але дозволяє компілятору зрозуміти, скільки елементів у ньому є.
jimt

5
Я думаю, що для постійних масивів потрібні оновлення системи типів. В іншому випадку, якби ви визначили функцію, f(xs [5]int)ви б не знали, чи пройшов масив постійний або змінений.
Thomas Ahle

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

Дякуємо за шматочок розчину. Сумніви: масив сам по собі незмінний, правда? Після створення масиву не можна додавати або видаляти елементи, ні? Однак я можу редагувати елементи масиву.
legends2k

@ legends2k Ви не можете змінити розмір масиву, так, але ви можете розмістити інші значення у його слотах.
Denys Séguret

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доступний лише у визначеному пакеті. Якщо вам потрібен доступ для читання ззовні, тоді ви можете написати просту функцію геттера (див. Getters in 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 ):

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
це звучить як найкращий шлях, однак тип повернення функціоналу не відповідає. 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[:]. (Літерали масиву не адресовані, мені незрозуміло, чому.)
Девід

Я не впевнений, що ти маєш на увазі. Це здається, що ви намагаєтеся вирішити щось у своєму коді, що, ймовірно, вирішено краще за допомогою (одиничних) тестів.
Дином
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.