Go言語で作るシンプルなToDoリスト:配列やスライスを学びながら基本を習得しよう

プログラミングを始めたばかりの方や、Go言語を学び始めたばかりの方にとって、「シンプルで楽しいプロジェクト」は上達への近道です。今回の記事では、初心者でも取り組みやすい「コマンドラインで動作するToDoリストアプリ」を作成しながら、Go言語の基本的な機能である配列、スライス、構造体、関数を学びます。プログラムを理解するだけでなく、次のステップとしてデータベースやWebインターフェースの導入に繋がる内容となっています。さあ、一緒にGo言語の世界を楽しみましょう!

プログラム全体の概要

このプログラムは、コマンドラインで動作するシンプルなToDoリストアプリケーションです。以下の機能を備えています。

解説している元ファイルはGitHubからダウンロードできます。
https://github.com/miyakawa2449/go_simple_todolist

  1. ToDoの追加: 新しいタスクをリストに追加します。
  2. ToDoの一覧表示: 現在のToDoリストを表示します。
  3. ToDoの完了マーク: 指定したToDoを「完了」としてマークします。
  4. ToDoの削除: 指定したToDoをリストから削除します。
  5. 終了: プログラムを終了します。

主な構成要素

  • ToDo構造体
    • タスクを表すデータ構造です。
    • フィールド:
      • ID: 一意の識別子。
      • Description: タスクの説明。
      • Done: タスクの完了状態(trueまたはfalse)。
  • グローバル変数
    • todos: 現在のToDoリストを格納するスライス。
    • nextID: 次に追加するタスクのID。
  • 関数
    • main: メインのプログラムループ。
    • addToDo: ToDoを追加。
    • listToDos: ToDoの一覧を表示。
    • markToDoAsDone: ToDoを「完了」にする。
    • deleteToDo: ToDoを削除。

ToDo型と関連する変数の解説

Go言語では、複雑なデータ構造を扱う際に**構造体(struct)**が重要な役割を果たします。このプログラムでも、ToDo型という構造体を定義することで、各タスクの情報を整理しています。

コード解説

type ToDo struct {
ID int
Description string
Done bool
}

  • 構造体ToDo
    • 各タスクを表現するデータ型です。
    • フィールド:
      • ID(int型): 各タスクを一意に識別するための番号。
      • Description(string型): タスクの説明。
      • Done(bool型): タスクの完了状態を表すフラグ。trueは完了、falseは未完了を示します。

このように構造体を使うことで、関連するデータを1つの単位としてまとめて扱うことができ、プログラムが整理されます。


var todos []ToDo
var nextID int = 1
  • todos(スライス)
    • タスクのリストを格納するスライスです。
    • スライスは可変長配列のように、要素を動的に追加したり削除したりできるGo言語の便利なデータ構造です。
    • プログラム内では、append関数を用いて新しいタスクをリストに追加しています。
  • nextID(int型)
    • 次に作成するタスクのIDを管理する変数です。
    • 初期値を1に設定しており、新しいタスクが追加されるたびに1ずつ増加します。
    • この変数を利用して、各タスクに一意のIDを付与します。

ポイント

  • 構造体の活用
    • 一つのタスクに関連する情報(ID、説明、完了状態)を構造体にまとめることで、プログラムが読みやすくなり、拡張性も高まります。
  • スライスの利用
    • スライスは要素数を動的に変更できるため、複数のタスクを扱う場合に最適です。
    • 今回のプログラムでは、スライスを使って複数のタスクをリストとして管理しています。

この部分の理解が、プログラム全体をスムーズに読み解く土台となります。構造体とスライスは、Go言語を使ったプログラムで頻繁に登場する重要な概念ですので、しっかり押さえておきましょう!

関数の詳細解説

1. main関数

func main() {
// ユーザーからの入力を処理するためにbufio.Scannerを使用。
scanner := bufio.NewScanner(os.Stdin)

for {
// メニュー表示。
fmt.Println("\n--- ToDo List ---")
fmt.Println("1. Add ToDo")
fmt.Println("2. List ToDos")
fmt.Println("3. Mark ToDo as Done")
fmt.Println("4. Delete ToDo")
fmt.Println("5. Exit")
fmt.Print("Choose an option: ")

// ユーザーの選択を取得。
scanner.Scan()
option := scanner.Text()

// 選択肢に応じて対応する処理を呼び出す。
switch option {
case "1":
addToDo(scanner)
case "2":
listToDos()
case "3":
markToDoAsDone(scanner)
case "4":
deleteToDo(scanner)
case "5":
// プログラム終了。
fmt.Println("Goodbye!")
return
default:
// 無効な入力に対するメッセージ。
fmt.Println("Invalid option, please try again.")
}
}
}

  • メインループでメニューを表示し、ユーザーの入力を処理します。
  • 選択肢に応じて適切な関数を呼び出します。

2. addToDo関数

func addToDo(scanner *bufio.Scanner) {
fmt.Print("Enter the ToDo description: ")
scanner.Scan()
description := scanner.Text() // ユーザーが入力した説明文を取得。

todo := ToDo{
ID: nextID,
Description: description,
Done: false, // 初期状態は未完了。
}
todos = append(todos, todo) // ToDoリストに追加。
nextID++ // 次のIDを更新。

fmt.Println("ToDo added successfully!")
}

  • ユーザーにタスクの説明を入力してもらい、todosスライスに新しいToDoを追加します。
  • タスクの初期状態はDone: falseです。

3. listToDos関数

func listToDos() {
if len(todos) == 0 {
fmt.Println("No ToDos available.") // 空のときのメッセージ。
return
}
fmt.Println("\nCurrent ToDos:")
for _, todo := range todos {
// 完了状態に応じてステータスを表示。
status := "Not Done"
if todo.Done {
status = "Done"
}
fmt.Printf("%d. [%s] %s\n", todo.ID, status, todo.Description)
}
}

  • ToDoリストを表示します。
  • 完了状態に応じて「Not Done」または「Done」を表示します。

4. markToDoAsDone関数

func markToDoAsDone(scanner *bufio.Scanner) {
fmt.Print("Enter the ID of the ToDo to mark as done: ")
scanner.Scan()
var id int
fmt.Sscanf(scanner.Text(), "%d", &id) // 入力を整数に変換。

for i, todo := range todos {
if todo.ID == id {
// 指定されたIDのタスクを「完了」に設定。
todos[i].Done = true
fmt.Println("ToDo marked as done!")
return
}
}
fmt.Println("ToDo not found.") // IDが見つからなかった場合。
}

  • 指定されたIDのToDoを検索し、Donetrueにします。

5. deleteToDo関数

func deleteToDo(scanner *bufio.Scanner) {
fmt.Print("Enter the ID of the ToDo to delete: ")
scanner.Scan()
var id int
fmt.Sscanf(scanner.Text(), "%d", &id)

for i, todo := range todos {
if todo.ID == id {
// スライスからタスクを削除。
todos = append(todos[:i], todos[i+1:]...)
fmt.Println("ToDo deleted successfully!")
return
}
}
fmt.Println("ToDo not found.") // IDが見つからなかった場合。
}

  • 指定されたIDのToDoをリストから削除します。
  • スライス操作を利用して要素を除去します。

次のステップ

次は以下を目指しましょう。

  1. データベース接続:
    • SQLiteなどの軽量データベースを使い、データを永続化します。
  2. HTMLインターフェース:
    • net/httpパッケージを使ってWebサーバーを構築し、ブラウザで操作できるようにします。

まとめ

この記事では、Go言語の基本的な要素を使ってシンプルなToDoリストアプリを作成しました。配列やスライスの操作、構造体を用いたデータ管理、標準入力での操作など、初学者にとって重要なトピックを網羅しています。この経験を活かし、次のステップとして以下の挑戦をおすすめします。

  1. データの永続化: SQLiteやMySQLを使って、データを保存する仕組みを導入。
  2. Webインターフェース: net/httpパッケージを使い、HTMLを通じて操作できるように拡張。
  3. ファイル操作: JSONやCSVファイルを使ってデータを保存・読み込みする練習。

今回のプロジェクトを通じて、Go言語の魅力と可能性を少しでも感じていただけたなら幸いです。これからもGo言語での学習を楽しみ、ぜひあなたのアイデアを形にしてください!

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール