Go言語での2次元配列の初期化方法を解説
Go(Go言語)で2次元配列を初期化する方法について解説します。
この記事では、基本的な配列の作成法から複雑な初期化方法まで、シンプルに説明していきます。
すでにGoの環境が構築されている方向けに、読みやすく実際のコード例も紹介しながら進めます。
基本的2次元配列の初期化方法
ここでは、Go言語で2次元配列を初期化する基本的な方法について説明します。
サンプルコードも含んでいるので、実際のコードと出力結果を参考にしてください。
固定長配列の宣言とリテラル初期化
配列の基本的な定義方法
固定長の2次元配列は、宣言時にサイズを決める必要があります。
例えば、要素数が3×3の整数型配列を宣言する場合は、以下のように記述します。
package main
import "fmt"
func main() {
	// 3行3列の固定長の2次元配列を宣言
	var matrix [3][3]int
	// 配列の初期値は全て0となる
	fmt.Println("固定長配列の初期状態:")
	fmt.Println(matrix)
}固定長配列の初期状態:
[[0 0 0] [0 0 0] [0 0 0]]リテラルによる初期値の設定
リテラルを使って配列を初期化することで、宣言と同時に値を設定できます。
例えば、2行3列の配列を使って、初期値を明示的に設定する場合は下記のように行います。
package main
import "fmt"
func main() {
	// リテラルによる初期化
	matrix := [2][3]int{
		{1, 2, 3},  // 1行目の初期値
		{4, 5, 6},  // 2行目の初期値
	}
	fmt.Println("リテラル初期化された固定長配列:")
	fmt.Println(matrix)
}リテラル初期化された固定長配列:
[[1 2 3] [4 5 6]]スライスを利用した初期化手法
スライスの作成と2次元構造の実現
固定長配列はサイズが固定ですが、スライスを使うことで動的な2次元配列が実現できます。
まず、外側のスライスを作成し、その後内側の各スライスを初期化する方法を紹介します。
package main
import "fmt"
func main() {
	// 行数と列数を定義
	rows, cols := 3, 3
	// 外側のスライスを作成
	matrix := make([][]int, rows)
	// 各行のスライスを作成し、初期状態を設定
	for i := 0; i < rows; i++ {
		matrix[i] = make([]int, cols)
	}
	fmt.Println("スライスを利用した2次元配列:")
	fmt.Println(matrix)
}スライスを利用した2次元配列:
[[0 0 0] [0 0 0] [0 0 0]]動的な初期化の実例
スライスの場合、各行のサイズは柔軟に設定できます。
また、動的に値を追加することも可能です。
以下の例では、行ごとに異なるサイズのスライスを生成し、初期値を設定しています。
package main
import "fmt"
func main() {
	// 行ごとに要素数が異なる2次元スライスを作成
	matrix := [][]int{
		{1, 2, 3},         // 1行目
		{4, 5},            // 2行目: 列数が異なる
		{6, 7, 8, 9},      // 3行目: 異なる列数
	}
	fmt.Println("動的に初期化されたスライス:")
	fmt.Println(matrix)
}動的に初期化されたスライス:
[[1 2 3] [4 5] [6 7 8 9]]実践的な初期化例
ここでは、ループや数式を用いた動的な初期化例について紹介します。
初期化パターンの選択で、変数の値に応じた設定が可能です。
ループを用いた各要素の初期化
forループでの要素設定例
forループを活用することで、各要素に初期値を設定できます。
ここでは、行数と列数に応じてすべての要素に同じ値(例: 1)を設定する例を示します。
package main
import "fmt"
func main() {
	// 配列サイズ
	rows, cols := 3, 3
	matrix := make([][]int, rows)
	// スライスの作成と初期値の設定
	for i := 0; i < rows; i++ {
		matrix[i] = make([]int, cols)
		for j := 0; j < cols; j++ {
			matrix[i][j] = 1  // 全項目に1を設定
		}
	}
	fmt.Println("forループを用いた初期化:")
	fmt.Println(matrix)
}forループを用いた初期化:
[[1 1 1] [1 1 1] [1 1 1]]インデックスを利用した初期化パターン
インデックス番号を活かして、例えば要素に行番号と列番号の合計値を設定するパターンです。
各要素の値がi+jとなるため、初期化パターンの例として分かりやすいです。
package main
import "fmt"
func main() {
	rows, cols := 3, 3
	matrix := make([][]int, rows)
	for i := 0; i < rows; i++ {
		matrix[i] = make([]int, cols)
		for j := 0; j < cols; j++ {
			matrix[i][j] = i + j  // インデックスの和を代入
		}
	}
	fmt.Println("インデックス利用の初期化パターン:")
	fmt.Println(matrix)
}インデックス利用の初期化パターン:
[[0 1 2] [1 2 3] [2 3 4]]数式を用いたパターン初期化
インデックスに基づく数式の利用例
各要素を数学的な計算式に基づいて初期化する方法もあります。
例えば、各要素を次の数式で初期化する場合、
\[ a_{ij} = i^2 + j^2 \]
と定義できます。
package main
import (
	"fmt"
	"math"
)
func main() {
	rows, cols := 3, 3
	matrix := make([][]int, rows)
	for i := 0; i < rows; i++ {
		matrix[i] = make([]int, cols)
		for j := 0; j < cols; j++ {
			// 数式: a_{ij} = i^2 + j^2 を用いて初期化
			matrix[i][j] = int(math.Pow(float64(i), 2) + math.Pow(float64(j), 2))
		}
	}
	fmt.Println("数式を用いた初期化 (a_{ij} = i² + j²):")
	fmt.Println(matrix)
}数式を用いた初期化 (a_{ij} = i² + j²):
[[0 1 4] [1 2 5] [4 5 8]]注意点とエラー回避策
初期化方法にはそれぞれ注意すべき点があります。
ここでは、型やサイズに関する不一致、また初期化時に発生しやすいエラーとその回避策について説明します。
型やサイズの不一致に関する留意点
配列とスライスの違いによる影響
配列とスライスには以下のような違いがあります。
- 配列は固定長で宣言時にサイズが決まるため、サイズ変更ができません。
 - スライスはサイズを動的に変更でき、柔軟なデータ構造となります。
 
この違いにより、初期化時に型やサイズが一致していないとコンパイルエラーが発生する可能性があります。
例えば、固定長の配列に対して不足する要素数でリテラルを記述するとエラーとなるので注意が必要です。
初期化時に発生しやすいエラー例
コンパイルエラーの原因と回避方法
コンパイルエラーは、主にサイズや型の不一致が原因となります。
以下の点に気を付けるとよいです。
- 配列のリテラル初期化時は、要素数が宣言と一致しているか確認する。
 - スライスの初期化時に、明示的にサイズを取り扱う場合は、対象の型とサイズが正しいことを確認する。
 
実行時エラーの対処法
実行時エラーとしては、以下のような点が考えられます。
- スライスに対して存在しないインデックスでアクセスすると、実行時パニックが発生するので、インデックス範囲を確認する。
 - ネストされたループでスライスの初期化が不完全な場合は、nil参照が発生する可能性があるため、各行を必ず初期化する。
 
以上、固定長配列とスライスの両方の初期化方法、および実践的な初期化例と注意点について説明しました。
各サンプルコードを実際に実行し、出力結果を確認しながら理解を深めてください。
まとめ
この記事では、Go言語における2次元配列の固定長配列の宣言やリテラル初期化、スライスを活用した動的初期化、さらにforループや数式を用いた実践的初期化およびエラー回避策について解説しました。
各手法の特徴や注意点を整理し、効果的な初期化方法が理解できる内容です。
ぜひ、各サンプルコードを実際に動かして、ご自身の開発プロジェクトで活用してみてください。