Go言語(golang)でTUIアプリを作ろう 第二部入魂編 ( その1 TUIアプリケーションの作成 )


先に10回の長きに渡って、golangのtviewモジュールを使用したTUI(Terminal base User Interface)アプリケーション開発について、Python Urwidとほぼ同様の機能を実装しながら進めてきました。tviewの基本概念と、主な部品の仕様についての説明をし終えたつもりですが、あくまでもUI部品の動作を示したにすぎません。やはり、Python Urwidによる実装同様、実際に動くTUIベースのアプリケーションに仕上げておかないと、中途半端な印象を拭えません。


[1] アプリケーションの仕様

そこで今回も、PythonでTUIアプリを作ろう 第二部入魂編(その1 個人データの管理を考える)PythonでTUIアプリを作ろう 第二部入魂編(その2 ListDBの構造について)で説明した簡易データベースアプリをターゲットに、実際に動くアプリケーションに仕上げていきましょう。アプリケーションの仕様については、上記のリンクを参照してください。


[2] golangによるDBアクセス

さて、言うまでもないことですが、アプリケーションの動作にはデータベースが必要となります。PythonにDB-APIがあったように、golangにはdatabase/sqlというデータベースアクセスに関する標準があり、インターフェースとして定義されています。詳細は下記を参照してください。

基本的に、データベースにアクセスするモジュールは、このインターフェースにしたがって開発されているはずなので、データベースの違いは一定吸収されてます。ただ、PythonでTUIアプリを作ろう 第二部入魂編(その7 Pythonのデータアクセス機能)で述べたように、「あくまで関数が共通化されただけで、SQLレベルまで合わされているわけではない」のは言うまでもありません。

先のPythonによるTUIアプリケーション開発には、SQLite3を使用を使用しました。これは、SQLite3がシングルユーザー向けデータベースとしてデファクトスタンダードなツールであるだけでなく、Pythonの標準ライブラリに含まれていることがその理由です。
golangの標準ライブラリには、具体的なデータベースへのアクセスモジュールは含まれていませんが、まずはSQLite3の利用を前提としてみました。


[3] SQLite3アクセスモジュール

golangにもSQLite3アクセスモジュールが用意されています。

実は、すでにこのモジュールを使用したTUIアプリケーションの実装は完了しています。機能的には何の問題もありません。ただ、今回のアプリケーションで使用するには、いささか気になる点があるのです。


[4] SQLite3アクセスモジュールの問題点

PythonでTUIアプリを作ろう(その1 TUIアプリとは)にて、「TUIアプリケーションは、多くの環境で汎用的に利用することが可能」と述べた上で、アプリケーションの目的を

汎用的な言語を使ってTUIアプリを作成、様々な環境で動作させること

であるとしました。

ただ、前回はPythonを使用しましたから、「動作環境上でPythonが動くこと」が前提条件であり、事前にインストールと環境設定を済ませておかねばなりませんでした。

今回、golangを使うにあたっては、そのような「前提条件なしでの動作を可能にしたい」と目論んでいました。

  • golangコンパイラでスタティックなバイナリを作成
  • 1つの実行ファイルのみでの動作
  • クロスコンパイルで、異なる環境の実行ファイルを生成

これらを可能にしたいというわけです。そのためには、依存関係のない独立オブジェクトを生成できないといけません。

ところが、このSQLite3アクセスモジュールは、C言語に依存しているのです。いわゆるCGOなのです。

This package requires the CGO_ENABLED=1 ennvironment variable if not set by default, and the presence of the gcc compiler.

例えば、Windows環境で使用するには、

To compile this package on Windows, you must have the gcc compiler installed.

とあります。
すなわち、開発時にはその環境にgccが必要であり、実行環境もgccのライブラリglibcに依存していることになり、バージョンが違うと動作しないと思われます。これは、今回のアプリケーション設計における初期ポリシーに反するものであり、golangのようなコンパイラを使うメリットがスポイルされることになってしまいます。


2024/10追記 SQLiteに対するPure Goのモジュールの利用

 これを書いていた同時期に 「SQLiteに対するPure Goのモジュール」 が開発されていたようです。

 2年近く経ってからようやく気がついくというお粗末な体たらくですが、今回当時開発していたコードをテストしてみましたが、database/sql標準に準拠されていますので、2箇所の変更だけで動作しました。

//import文  
import (  
      :  
  
	_ "github.com/glebarez/go-sqlite"  
	//_ "github.com/mattn/go-sqlite3"  
}  
// DB Open時の文字列  
	//sqlite3.Db , err = sql.Open("sqlite3", connectString)  
	sqlite3.Db, err = sql.Open("sqlite", connectString)  

データアクセス機能検証のため、こちらのモジュールを使用した MySQL 対応も入れておきます。
なお、MySQLの設定などは、「PythonでTUIアプリを作ろう 第二部入魂編(その7 Pythonのデータアクセス機能)」を参照してください。

ユーザーID           "user01"  
パスワード           "pass01"  
サーバーのアドレス    "192.168.0.33"  
データベース          "ListDB"  

の場合、接続文字列は下記となります。

user01:pass01@tcp(192.168.0.33:3306)/ListDB  
  

上記モジュールを使用したソースを GitHub に登録しました。コードは、こちら です。

これがあれば、以下の苦労は必要なかったのでしょうが、まあ、いろいろな機能をテストするのは楽しいものですから良しとしておきます。なお、次項で取り上げた BoltDB は取っ付きは悪いですが、性能が良いので、Webアプリケーションなどでの採用も悪くない選択だと思っています。
(以上 追記)


[5] 対応施策

上記の課題を解決する施策は唯一つ、golangでスタティックにコンパイルできるデータベース、すなわちgolang自身で書かれたデータベースを探し出し、使用することにつきます。

次回はその対応について説明しましょう。