Deklarieren Sie ein konstantes Array

164

Ich habe versucht:

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 }

Erstens funktionieren Deklaration und Initialisierung einwandfrei, aber die zweite, dritte und vierte funktionieren nicht. Wie kann ich ein const-Array von Floats deklarieren und initialisieren?

demas
quelle

Antworten:

231

Ein Array ist von Natur aus nicht unveränderlich. du kannst es nicht konstant machen.

Der nächste, den Sie bekommen können, ist:

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 }

Beachten Sie das [...]anstelle von []: Es stellt sicher, dass Sie ein Array (fester Größe) anstelle eines Slice erhalten. Die Werte sind also nicht festgelegt, sondern die Größe.

Denys Séguret
quelle
126
Nur zur Verdeutlichung: Die [...]TSyntax ist Zucker für [123]T. Es erstellt ein Array mit fester Größe, lässt den Compiler jedoch herausfinden, wie viele Elemente sich darin befinden.
Jimt
5
Ich denke, das Zulassen konstanter Arrays würde Aktualisierungen des Typsystems erfordern. Andernfalls f(xs [5]int)würden Sie nicht wissen, ob das übergebene Array konstant oder veränderlich ist, wenn Sie eine Funktion definiert haben .
Thomas Ahle
tks, ich habe Probleme, wenn ich versuche, Saiten.Join cannot use constants.FilesRequired (type [4]string) as type []string in argument to strings.Join
Eddy Hernandez
Danke für die Slice-Lösung. Zweifel: Ein Array selbst ist unveränderlich, oder? Man kann keine Elemente hinzufügen oder entfernen, sobald ein Array erstellt wurde, oder? Ich kann jedoch die Array-Elemente bearbeiten.
Legends2k
@ legends2k Sie können die Größe des Arrays nicht ändern, ja, aber Sie können andere Werte in seine Slots einfügen.
Denys Séguret
63

Von Anfang an :

Konstanten in Go sind genau das - Konstante. Sie werden zur Kompilierungszeit erstellt, auch wenn sie in Funktionen als lokale Elemente definiert sind, und können nur Zahlen, Zeichenfolgen oder Boolesche Werte sein. Aufgrund der Einschränkung der Kompilierungszeit müssen die Ausdrücke, die sie definieren, konstante Ausdrücke sein, die vom Compiler ausgewertet werden können. Zum Beispiel ist 1 << 3 ein konstanter Ausdruck, während math.Sin (math.Pi / 4) dies nicht ist, weil der Funktionsaufruf von math.Sin zur Laufzeit erfolgen muss.

Slices und Arrays werden immer zur Laufzeit ausgewertet:

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

[...]Weist den Compiler an, die Länge des Arrays selbst herauszufinden. Slices umschließen Arrays und sind in den meisten Fällen einfacher zu bearbeiten. Anstatt Konstanten zu verwenden, machen Sie die Variablen einfach für andere Pakete unzugänglich, indem Sie einen Anfangsbuchstaben in Kleinbuchstaben verwenden:

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

thisIsPrivateist nur in dem Paket verfügbar, das es definiert hat. Wenn Sie Lesezugriff von außen benötigen, können Sie eine einfache Getter-Funktion schreiben (siehe Getter in Golang ).

Fasmat
quelle
12

In Go gibt es keine Array-Konstante.

Zitat aus der Go-Sprachspezifikation: Konstanten :

Es gibt boolesche Konstanten , Runenkonstanten , Ganzzahlkonstanten , Gleitkommakonstanten , komplexe Konstanten und Zeichenfolgenkonstanten . Runen-, Ganzzahl-, Gleitkomma- und komplexe Konstanten werden gemeinsam als numerische Konstanten bezeichnet .

Eine Constant - Expression (die verwendet wird , eine Konstante zu initialisieren) enthalten kann nur konstante Operanden enthalten und wird zur Kompilierungszeit ausgewertet.

In der Spezifikation sind die verschiedenen Konstantentypen aufgeführt. Beachten Sie, dass Sie Konstanten mit konstanten Ausdrücken von Typen erstellen und initialisieren können, die einen der zulässigen Typen als zugrunde liegenden Typ haben . Zum Beispiel ist dies gültig:

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)
}

Ausgabe (versuchen Sie es auf dem Go-Spielplatz ):

main.Myint 1
main.Myint 2

Wenn Sie ein Array benötigen, kann es nur eine Variable sein, aber keine Konstante.

Ich empfehle diesen großartigen Blog-Artikel über Konstanten: Konstanten

icza
quelle
Was tun, wenn ein Behälter mit konstanter Größe benötigt wird?
@Atomic_alarm Kannst du das bitte näher erläutern?
icza
Existiert ob im Golang-Analog-C-Array?
@Atomic_alarm Ja, Arrays existieren auch in Go. Sie sind nur keine konstanten Ausdrücke, sondern werden zur Laufzeit ausgewertet. Eine Konstante kann also nicht vom Typ Array sein, sondern eine Variable. Zum Beispiel:var arr = [2]int{2, 3}
icza
3

Wie andere bereits erwähnt haben, gibt es dafür kein offizielles Go-Konstrukt. Das nächste, was ich mir vorstellen kann, wäre eine Funktion, die ein Slice zurückgibt. Auf diese Weise können Sie sicherstellen, dass niemand die Elemente des ursprünglichen Slice manipuliert (da es im Array "fest codiert" ist).

Ich habe deine Scheibe gekürzt, um sie ... kürzer zu machen ...:

func GetLetterGoodness() []float32 {
    return [...]float32 { .0817,.0149,.0278,.0425,.1270,.0223 }
}
Paul
quelle
4
Dies klingt nach dem besten Weg, jedoch stimmt der Funkrückgabetyp nicht überein. cannot use [6]string literal (type [6]string) as type []string in return argumentsoreturn []float32 { ... }
theRemix
@theRemix Drei mögliche Korrekturen: (1) Entfernen ..., um ein Slice-Literal anstelle eines Array-Literals zu deklarieren. (2) Ändern Sie den Rückgabetyp in [6]float32. (3) Weisen Sie den Ausdruck einer Array-Variablen zu a := [...]float32 { (etc.) }und geben Sie den Slice aller Elemente zurück : return a[:]. (Array-Literale sind nicht adressierbar, ich weiß nicht warum.)
David Moles
Ich bin mir nicht sicher, was Sie damit meinen. Es hört sich so an, als würden Sie versuchen, etwas in Ihrem Code zu lösen, das wahrscheinlich mit (Einheits-) Tests besser gelöst werden kann.
Dynom