こんにちは。KOUKIです。
とある企業でWeb系の開発業務に従事しています。メインはGo言語です。
今日は、Arrayのオススメな使い方について記事にしました。まぁ、以前も同じような記事を書いたのですが、もう少し掘り下げてみようかと。
Arrayの書き方に偏見を持ってない?
最初に質問せてください。Arrayの書き方に次のような偏見を持ってませんか?
1 2 3 4 5 6 7 8 |
package main import "fmt" func main() { var books [4]string fmt.Printf("Books contents: %v\n", books) } |
話題にしたいのは、「var books [4]string」の数値の部分です。
ご存知の通り、Arrayは長さが決まっているデータセットですが、長さには「数値を直接代入する」のが一般的なセオリーですよね。
しかし、次のような書き方もできるのです。
1 2 3 4 5 6 7 8 |
const ( savedBookNumber = 4 // 定数を定義 ) func main() { var books [savedBookNumber]string // 定数を使う fmt.Printf("Books contents: %v\n", books) } |
1 2 |
$ go run main.go Books contents: [ ] |
はい。別に数字じゃなくてもOKって感じです。
「いやいや知ってるけど」という人は無視してください。だけど、意外に盲点だった!という人もいるのではないでしょうか?「あ、できたんだ…」みたいな。
「savedBookNumber」のような変数は説明変数と呼ばれており、プログラムの可読性を大幅に向上します。
Arrayの初期化、ちゃんと活用できてる?
Arrayの初期化処理に書きがちなのが、以下のコードです。
1 2 3 4 5 6 7 8 |
func main() { var books [savedBookNumber]string books[0] = "Harry Potter" books[1] = "俺の青春ラブコメは絶対間違っている" books[2] = "我輩は猫である" books[3] = "Never Ending Story" fmt.Printf("Books contents: %v\n", books) } |
これも悪くはないのですが、宣言と同時に初期化しちゃった方がシンプルです!
1 2 3 4 5 6 7 8 9 10 11 |
func main() { books := [savedBookNumber]string{ "Harry Potter", "俺の青春ラブコメは絶対間違っている", "我輩は猫である", "Never Ending Story", } fmt.Printf("Books contents: %v\n", books) } |
1 2 |
$ go run main.go Books contents: [Harry Potter 俺の青春ラブコメは絶対間違っている 我輩は猫である Never Ending Story] |
玄人には当たり前の書き方なのですが、意外に盲点だったりするんですよね。
ちなみに、要素数全てにデータを入力しなくてもデータ型の初期値が入るので大丈夫です。
1 2 3 4 5 6 7 |
func main() { books := [savedBookNumber]string{ "Harry Potter", } fmt.Printf("Books contents: %#v\n", books) } |
1 2 |
$ go run main.go Books contents: [4]string{"Harry Potter", "", "", ""} |
省略記号「…」が便利だってことを教えてあげよう
皆さんは、省略記号「…」を活用できてますか?ちなみに私はできてませんw
結構便利なんですよ。これ。
1 2 3 4 5 6 7 8 9 10 |
func main() { books := [...]string{ "Harry Potter", "俺の青春ラブコメは絶対間違っている", "我輩は猫である", "Never Ending Story", } fmt.Printf("Books contents: %v\n", books) } |
savedBookNumberの代わりに、「…」を代入しました。これがどうなるかというと…
1 2 |
$ go run main.go Books contents: [Harry Potter 俺の青春ラブコメは絶対間違っている 我輩は猫である Never Ending Story] |
ご覧の通り、ちゃんと処理ができます!初期化したデータに基づいてArrayの長さを決めてくれるようですね。
「え?これならスライス使えばいいんじゃない?」という声が聞こえてきそうですが…

Arrayは、長さが決まっているデータセットなので、要素数をオーバーすると上の画像のようにエラーになります!
ループはこうやって処理できるよ?
次は、Arrayと切って離せない存在であるループ処理です。Arrayとループ処理は、蜜月な関係ですよね^^
しかし、以下のように「いけてないコード」をよく見かけます。
1 2 3 4 5 6 7 8 9 10 11 12 |
func main() { books := [savedBookNumber]string{ "Harry Potter", "俺の青春ラブコメは絶対間違っている", "我輩は猫である", "Never Ending Story", } for i := 0; i < len(books); i++ { fmt.Printf("No.%d: %v\n", i, books[i]) } } |
「これの何が悪いんだ!」と怒られるかもしれませんね。しかしこの書き方だと、たまに「要素数を超えてアクセスする可能性」がありますよね?
以下のように書きましょう。
1 2 3 4 5 6 7 8 9 10 11 12 |
func main() { books := [savedBookNumber]string{ "Harry Potter", "俺の青春ラブコメは絶対間違っている", "我輩は猫である", "Never Ending Story", } for i, v := range books { fmt.Printf("No.%d: %v\n", i, v) } } |
1 2 3 4 5 |
$ go run main.go No.0: Harry Potter No.1: 俺の青春ラブコメは絶対間違っている No.2: 我輩は猫である No.3: Never Ending Story |
rangeキーワードを使えばOKです。Arrayの長さ分しかループしないので、要素数をオーバーすることはありません。
Keyを数値以外で指定する方法
ArrayのKeyは普通数値で指定しますよね?こんな感じで。
1 2 3 4 |
rates := []float64{ 0: 1.2, 1: 1.2, } |
このKeyを数値以外で指定する方法を紹介します。
紹介の前に、少し小話をさせて下さい。
下記のコードは、Arrayの初期化と宣言を同時に行なっています。
1 2 3 4 5 6 7 8 9 10 11 12 |
package main import "fmt" func main() { rates := [...]float64{ 5: 1.5, // key 5 2.5, // key なし 0: 0.5, // key 0 } fmt.Printf("rates value: #%v\n", rates) } |
このコードが面白いのは、初期化時にKeyを宣言していたり、しなかったりしているところです。
この様な書き方は、あまりしないですよね? 結果は、以下のようになりました。
1 2 |
$ go run main.go rates value: [7]float64{0.5, 0, 0, 0, 0, 1.5, 2.5} |
rate配列は初期化時にデータの長さが決まる可変長引数(…)を指定しています。そのため、 Keyを指定していない(2.5)場合は、最後のKey(5)の後にデータが追加されるようです。
さて、本題に戻ります。
Keyには、数値が指定されていればOKです。つまり、以下のようにすれば数値以外のKeyを指定することができます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package main import "fmt" func main() { const ( ETH = iota WAN ) rates := [...]float64{ ETH: 1.5, WAN: 120.5, } fmt.Printf("rates value: %#v\n", rates) } |
1 2 |
$ go run main.go rates value: [2]float64{1.5, 120.5} |
iotaは、定数内で規定される識別子で、0から形無しの整数を生成します。
つまり、ETH=0, WAN=1の感じで数値が入るので、Keyの代わりになります。
ArrayのKeyは、0以上でないといけないので(負の値はいれられない)、この方法以外ではKeyの代わりにできないかもしれません。
試しにuint型でKeyの代替を試みましたが、エラーになりました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package main import "fmt" func main() { var ( ETH uint = 0 WAN uint = 1 ) rates := [...]float64{ ETH: 1.5, WAN: 120.5, } fmt.Printf("rates value: %#v\n", rates) } |

1 |
index must be non-negative integer constant |
おわりに
Go言語には、SliceやらArrayやらMapやら、色々なデータセットがあります。しかし、これはGo言語に限った話ではなく、JavaやPythonなど様々なプログラミング言語に存在します。
そのため、一つの言語でデータセットを極めれば、割と他の言語でも応用が効きます!
本当に大切なことなので、しっかり学んでおきたいですね^^
それでは、また!
最近のコメント