定数配列を宣言する


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 }

最初に、宣言と初期化は正常に機能しますが、2番目、3番目、4番目は機能しません。floatの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。固定サイズの配列を作成しますが、コンパイラーはその中に要素がいくつあるかを把握できます。
2012年

5
定数配列を許可するには、型システムの更新が必要になると思います。そうでなければ、関数を定義したf(xs [5]int)場合、渡された配列が定数か可変かがわかりません。
Thomas Ahle

私はstrings.JoinしようとするとTKS、私は問題を抱えている cannot use constants.FilesRequired (type [4]string) as type []string in argument to strings.Join
エディ・ヘルナンデス

スライスソリューションをありがとう。疑問:配列自体は不変ですよね?配列が作成されると、要素を追加または削除できません。ただし、配列要素は編集できます。
legends2k 2017年

@ legends2k配列のサイズを変更することはできませんが、他の値をそのスロットに入れることはできます。
DenysSéguret2017年

63

効果的なGoから:

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言語仕様からの引用:定数

あり、ブール定数ルーン定数整数定数浮動小数点定数複素数定数、および文字列定数。ルーン、整数、浮動小数点、および複素定数は、まとめて数値定数と呼ばれます

定数式(定数を初期化するために使用されている)のみを含んでいてもよい定数オペランドを、コンパイル時に評価されます。

仕様には、さまざまなタイプの定数がリストされています。許可されたタイプの1つを基本タイプとして持つタイプの定数式を使用して、定数を作成および初期化できることに注意してください。たとえば、これは有効です。

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

golangアナログCアレイに存在するかどうか。

@Atomic_alarmはい、配列はGoにも存在します。これらは定数式ではなく、実行時に評価されます。したがって、定数は配列型にすることはできませんが、変数はできます。例:var arr = [2]int{2, 3}
icza 2015年

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 3つの可能な修正:(1)削除し...て、配列リテラルの代わりにスライスリテラルを宣言します。(2)戻り値の型をに変更し[6]float32ます。(3)式を配列変数に割り当て、a := [...]float32 { (etc.) }すべての要素のスライスを返しますreturn a[:]。(配列リテラルはアドレス指定できません。理由はわかりません。)
David Moles

何を意味するのかわかりません。(ユニット)テストで解決される可能性が高いコードを解決しようとしているようです。
Dynom
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.