💭

Goで誕生日の報告・管理をしてくれるコマンドを作った!

2025/03/11に公開

はじめに

はじめまして、あさめしです。Go言語で友達や身内の誕生日を報告・管理してくれるコマンドを開発しました。
https://github.com/CrazyHuman00/CLI-Birthday-Reminder
birthday-reminderといいます。本記事では、GoでCLIコマンドを実装・公開・配布までを備忘録的に残したものとなっています。

開発経緯

友達や身内の誕生日は簡単に覚えられそうで、なかなか忘れがちです。そこでmacのターミナル起動時に誕生日を報告してくれる機能とその誕生日を管理できるコマンドがあれば便利ではと思い至ったのがことの経緯です。

機能説明

コマンドで誕生日の表示・追加・更新・削除を行えます。基本的にはbirthdayとコマンドと打って、オプションをつけることで実行可能です。

誕生日リストの確認(list)

保存されている誕生日のリストを表示します。左側に名前、右側がその人の誕生日がセットになっていて、保存されている誕生日を全て日付昇順で表示します。

$ birthday list
         xxx 01/01
         yyy 01/02
         zzz 01/03

誕生日の追加(add)

誕生日を名前と日付とセットで保存します。addの後に名前と誕生日の順で宣言して追加します。

$ birthday add xxx 01/01
Birthday added successfully! xxx's birthday is on 01/01

誕生日の更新(update)

既存のユーザの誕生日を更新します。updateの後に名前と更新したい誕生日を指定して実行します。成功しlistオプションで確認するとしっかりと更新されていることがわかりますね。

$ birthday update xxx 01/04
Birthday updated successfully! xxx's birthday is now on 01/04
$ birthday list
         yyy 01/02
         zzz 01/03
         xxx 01/04

誕生日の削除(remove)

追加した誕生日を削除することもできます。removeの後に名前を入力することで、削除することが可能です。

$ birthday remove xxx
Birthday removed successfully! xxx's birthday has been removed
$ birthday list
         yyy 01/02
         zzz 01/03

使用方法

環境構築

まずはGo言語の環境構築を行わなければなりません。ここでは割愛しますが、著者は以下のバージョンで使用しています。

$ go version
go version go1.24.0 darwin/arm64

そうしたら次に作成したリポジトリをクローンする必要があります。できればHOMEディレクトリ直下だとパスがわかりやすいかなと感じます。
https://github.com/CrazyHuman00/CLI-Birthday-Reminder

$ cd ~/
$ git clone https://github.com/CrazyHuman00/CLI-Birthday-Reminder

最後にbirthday listというコマンドを入力するとデータベースが作成されますので、実行をお願いします。

bashrc/zshrcに追記

最後にご自身が使われているシェルに以下の文を記入してください。

bashrc
#### birthday ####
(cd $HOME/CLI-Birthday-Reminder; birthday today)
### 著者の場合 ###
(cd $HOME/bin-birthday; birthday today)

最後に以下のコマンドを実行してシェルを保存します。

$ source ~/.bashrc

これを記入することにより、ターミナルの起動時に、今日誕生日の人の一覧が実行されるようになります。

Today's birthdays:
         xxx 03/11

CLIコマンド開発用のライブラリ - Cobra

今回使用したCobraはGoでCLIコマンドを実装するライブラリの一つです。
https://github.com/spf13/cobra
CobraはCLIアプリケーションの実装をサポートするためのライブラリです。
詳しい利用方法はドキュメントやgithubのリポジトリを見てください。

CobraはGoで実装されているため、インストールは以下でOKです。

go get -u github.com/spf13/cobra@latest

今回以下のように実装を行いました。

main.go
func main() {
	cmd.Execute()
}
root.go
var rootCmd = &cobra.Command{
	Use: "birthday",
	Short: "Birthday reminder system",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Hello birthday-reminder!")
	},
}

func Execute() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

これでbirthdayコマンドの基礎が完成しました。思ったより簡単です。
サブコマンドも実装可能です。
以下のようなexec.goを実装することで、誕生日を追加するaddコマンドを実装することができます。サブコマンドAddCmdはメソッドAddCommandを実行するコマンドであり、rootCmd.AddCommand(AddCmd)でrootに追加する感じです。
メソッド内ではデータベースを接続して、文字列型で受け取った名前と誕生日を型変換して追加する仕組みです。他のサブコマンドも似たような処理です。データベースの接続はGoのgormライブラリを使って実装をしました。
https://gorm.io/ja_JP/docs/index.html

exec.go
// 誕生日を追加するコマンド
var AddCmd = &cobra.Command{
	Use:   "add [name] [date]",
	Short: "Add a new birthday",
	Args:  cobra.ExactArgs(2),
	RunE: func(cmd *cobra.Command, args []string) error {
		return AddCommand(args[0], args[1])
	},
}
/** 省略 **/

// 初期化
func init() {
	rootCmd.AddCommand(AddCmd)
	rootCmd.AddCommand(ListCmd)
	rootCmd.AddCommand(RemoveCmd)
	rootCmd.AddCommand(UpdateCmd)
}

// 誕生日を追加するメソッド
func AddCommand(username string, birthday string) error {
	// DBに接続
	dbConn := db.ConnectDB()
	defer db.CloseDB(dbConn)
	dbConn.AutoMigrate(&model.UserBirthday{})

	birthdayTime, err := time.Parse("01/02", birthday)
	if err != nil {
		log.Fatalln(err)
	}

	// 誕生日を追加
	result := dbConn.Create(&model.UserBirthday{Name: username, Birthday: birthdayTime})
	if result.Error != nil {
		return result.Error
	}

	fmt.Printf("Birthday added successfully! %s's birthday is on %s\n", username, birthday)
	return nil
}

/** 省略 **/

db.go
// DBに接続する
func ConnectDB() *gorm.DB{
	db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
	if err != nil {
        log.Fatalln(err)
    }
	return db
}

// DBを切断する
func CloseDB(db *gorm.DB) {
	sqlDB, _ := db.DB()
	if err := sqlDB.Close(); err != nil {
		log.Fatalln(err)
	}
}

拡張性

サブコマンドを追加していけば拡張は色々できると思います。macのみの対応となっていますが、ターミナルのみでしか動作しません。そのため、バイナリなどで配布できたらなと思います。また皆様自らがこのコマンドを拡張していって構いませんので、色々試してみてください。

最後に

GoでCLIコマンドを実装してみましたが、Cobraライブラリのおかげで思ったより難しくなかったです。このコマンドはOSSとして公開していますので、ライセンスに沿ってご自由にご利用ください。

参考文献リンク
https://zenn.dev/tttol/articles/c7dfc74d27e45d

Discussion