- 投稿日:2021-02-26T21:18:32+09:00
プログラミング超入門(1)〜GO言語〜
Visual Studio Code(ビジュアル スタジオ コード)略してvscodeをインストールしてプログラムを実行してみる。
まず、Japanese Language Pack for Visual Studio Code(日本語翻訳)とGo言語の拡張機能を
vscode内でインストールしましょう。
新規フォルダからファイルを作成し、run.goという名前でコードを書いてみましょう。名前のrunは実行を意味し、( . )ピリオドの後に拡張子のgoを付けることで、Go言語だと自動的に判断してくれます。
run.gopackage main import "fmt" func main() { var a int a = 3 fmt.Println(2 * a) }前回の記事で説明した続きになりますが、var a intはそれぞれ意味を持っていて、
varは予約語(あらかじめ定められた役目を持った単語)であり、packageやimportも
それに当たります。予約語は変数名として使用することは出来ません。そしてvarは
変数名を宣言する(変数であることを示す)為に使われ、aが変数名に当たります。
次にintはデータ型(あるデータを保持しておく為に必要なメモリ領域の大きさ)を指します。
変数とは文字や数字などのデータを入れて置くことができる箱のようなもので、必要な
時にいつでもデータを取り出すことができます。変数にデータを入れることを代入と
いい、データを取り出すことを参照といいます。初めて変数にデータを入れることを
変数の初期化といい、変数を宣言する(変数を作る)作業に繋がります。変数aに=で3を
代入し、文字列や変数の中身を参照させる為に、Println(プリントライン関数を使います。
この変数の宣言と同時にデータを省略し代入することも可能です。run.gopackage main import "fmt" func main() { var a = 3 fmt.Println(2 * a) }まずは省略してみます。変数aの後にいきなり3を代入してあります。Goが自動的に
データ型を判断してくれているので上記と同じ結果が返ってきます。run.gopackage main import "fmt" func main() { a := 3 fmt.Println(2 * a) }更にシンプルに変数名a コロン: イコール= 代入したい値3で変数の宣言と同時に代入させ
る宣言方法がGoではよく使用されています。ファイルを保存し、ターミナルを開いて実行してみましょう。・実行結果
go build run.go 6go buildの後にファイル名run.goエンターして、./intsでエンターキーで、ビルド・実行
[ 6 ]が表示されました。
- 投稿日:2021-02-26T17:19:38+09:00
取り出したデータを条件分岐してGoの多次元スライスに入れる方法
はじめに
DBから取り出したデータを多次元構造にしてから処理する必要があったので実装を考えてみました。
例えば教科・科目を持つ学生のテーブルがあるとして、同じ教科・科目の組み合わせを持つ学生を同じ配列のなかに入れたいとします。プログラム
package main import ( "fmt" "sort" ) type student struct { studentID uint64 subjectAreaCode string subjectCode string } func main() { // テストデータ students := []student{ {1, "001", "002"}, {2, "002", "003"}, {3, "003", "004"}, {4, "004", "005"}, {5, "001", "005"}, {6, "003", "004"}, {7, "004", "005"}, } // あとで隣り合うものを比較するため一旦並び替える sort.Slice(students, func(i, j int) bool { return students[i].subjectAreaCode < students[j].subjectAreaCode }) sort.Slice(students, func(i, j int) bool { return students[i].subjectCode < students[j].subjectCode }) // 初期化 multiStudents := make([][]*student, len(students)) var ac1, ac2 string // 教科コード var c1, c2 string // 科目コード var n int // 教科・科目ごとに分類(多次元スライス) for i, h := range students { // 最初の要素は普通に入れる if i == 0 { multiStudents[n] = append(multiStudents[n], &h) ac1 = h.subjectAreaCode c1 = h.subjectCode continue } ac2 = h.subjectAreaCode c2 = h.subjectCode if ac1 == ac2 && c1 == c2 { multiStudents[n] = append(multiStudents[n], &h) } else { n++ multiStudents[n] = append(multiStudents[n], &h) } ac1 = h.subjectAreaCode c1 = h.subjectCode } // 空要素を取り除く var m [][]*student for _, v := range multiStudents { if len(v) > 0 { m = append(m, v) } } // 出力確認 for _, v := range m { fmt.Println(v) } // この後処理が続く return }解説
スライスを初期化して、取り出したデータ分の長さと容量を確保します。
multiStudents := make([][]*student, len(students))最初のループでは要素はそのまま格納し、その教科・科目コードを変数に入れます。
2回目以降のループでは比較する教科・科目コードを別の変数に入れ、両方一致する場合は同じ要素のスライスに入れます。一致しない場合は次の要素のスライスに入れていきます。
ループで隣り合うもの同士を比較するため、前処理でソートしています。for i, h := range students { if i == 0 { multiStudents[n] = append(multiStudents[n], &h) ac1 = h.subjectAreaCode c1 = h.subjectCode continue } ac2 = h.subjectAreaCode c2 = h.subjectCode if ac1 == ac2 && c1 == c2 { multiStudents[n] = append(multiStudents[n], &h) } else { n++ multiStudents[n] = append(multiStudents[n], &h) } ac1 = h.subjectAreaCode c1 = h.subjectCode }改善したい点
上記の方法で初期化すると、場合によっては空要素ができてしまいます。
[{1 001 002}] [{2 002 003}] [{3 003 004} {6 003 004}] [{5 001 005}] [{4 004 005} {7 004 005}] [] []
かといって初期化時に長さ・容量を確保しないと、最初のループで要素を格納するときにパニックになります。
var multiStudents [][]*studentmultiStudents[n] = append(multiStudents[n], &h) // => panic: runtime error: index out of range [0] with length 0なので今回は仕方なくあとで空要素を取り除いて処理しています。
この部分をもっと綺麗にできないかと思っています。まとめ
多次元構造でのスライス格納処理をしてみました。
ループのなかで比較する教科・科目コードを変数に入れていく位置がポイントでした。一致確認をする前に次の比較対象を入れ、一致確認後に今の比較対象をいれています。