前回、手軽にGo言語で簡易Webサーバーの作り方を紹介しました。Go言語を使えば数行で手軽にサーバーを作成できます。今回は、Webブラウザで手軽に使えるメモ帳を作ってみましょう。

  • 今回作成するWebブラウザで使えるメモアプリ

    今回作成するWebブラウザで使えるメモアプリ

Webサーバーの作り方の復習

前回、簡易Webサーバーの作り方を紹介しました。Go言語を使えば、簡単なプログラムで自作サーバーアプリが作れます。

最初に、簡単にWebサーバーの作り方を復習してみましょう。以下は、画面に「Hello」と表示するだけのWebサーバーですが、サーバーアプリの本質となる部分を備えています。以下のプログラムを「test_server.go」という名前で保存してください。

package main
import "net/http"
func main() {
  // URIに対応するハンドラを登録 --- (*1)
  http.HandleFunc("/", rootHandler)
  http.HandleFunc("/aaa", aaaHandler)
  http.HandleFunc("/bbb", bbbHandler)
  // サーバーを起動 --- (*2)
  http.ListenAndServe(":8888", nil)
}
// ハンドラを定義 --- (*3)
func rootHandler(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("Hello")) // Helloと出力
}
func aaaHandler(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("aaa")) // aaaと出力
}
func bbbHandler(w http.ResponseWriter, r *http.Request) {
  w.Write([]byte("bbb")) // bbbと出力
}

コマンドラインで以下のコマンドを実行してみましょう。

go run test_server.go

これを実行するとサーバーが起動します。その後、Webブラウザを開いて「http://localhost:8888」にアクセスしてみましょう。すると、画面にHelloと表示されます。

  • テストプログラムを実行したところ

    テストプログラムを実行したところ

さらに、「http://localhost:8888/aaa」にアクセスしてみましょう。画面に「aaa」と表示されます。次に「http://localhost:8888/bbb」にアクセスしてみましょう。すると、画面に「bbb」と表示されます。

この点を確認した上で、プログラムを見てみましょう。プログラムの(*1)の部分では、HandleFuncを利用して、サーバーのURIに対応するハンドラを登録します。「/」であれば関数rootHandlerを実行し、「/aaa」であれば関数aaaHandlerを、「/bbb」であれば関数bbbHandlerを実行するというものです。

そして、(*2)の部分でハンドラを登録したら、サーバーを起動します。(*3)以下の部分では、指定のURLに実際にアクセスがあったときに実行する関数(ハンドラ)を定義します。

このように、HandleFunc を利用して、指定したURIに対応したGoの関数が実行されるという点を覚えておきましょう。

メモ帳を作ろう - Webフォームの処理の仕方

次に、メモ帳アプリを作成してみます。以下のプログラムを「memo_server.go」という名前で保存します。

package main
import (
  "net/http"
  "io/ioutil"
  "html"
  "fmt"
)
const saveFile = "memo.txt" // データファイルの保存先
func main() { // メインプログラム
  // サーバーを起動する --- (*1)
  print("memo server - [URL] http://localhost:8888/\n")
  http.HandleFunc("/", readHandler) // ハンドラを登録
  http.HandleFunc("/w", writeHandler)
  http.ListenAndServe(":8888", nil) // 起動
}

// ルートへアクセスした時メモを表示 --- (*2)
func readHandler(w http.ResponseWriter, r *http.Request) {
  // データファイルを開く
  text, err := ioutil.ReadFile(saveFile)
  if err != nil { text = []byte("ここにメモを記入してください。") }
  // HTMLのフォームを返す
  htmlText := html.EscapeString(string(text))
  s := "<html>" +
       "<style>textarea { width:99%; height:200px; }</style>" +
       "<form method='POST' action='/w'>" +
       "<textarea name='text'>" + htmlText + "</textarea>" +
       "<input type='submit' value='保存' /></form></html>";
  w.Write([]byte(s))
}

// フォーム投稿した時 --- (*3)
func writeHandler(w http.ResponseWriter, r *http.Request) {
  // 投稿されたフォームを解析
  r.ParseForm()
  if (len(r.Form["text"]) == 0) { // 値が書き込まれてない時
    w.Write([]byte("フォームから投稿してください。"))
    return
  }
  text := r.Form["text"][0]
  // データファイルへ書き込む
  ioutil.WriteFile(saveFile, []byte(text), 0644)
  fmt.Println("save: " + text)
  // ルートページへリダイレクトして戻る --- (*4)
  http.Redirect(w, r, "/", 301)
}

プログラムを実行するには、コマンドラインで以下のように実行します。

go run memo_server.go

続いて、Webブラウザで表示されるURL「http://localhost:8888/」にアクセスしましょう。するとテキストボックスと保存ボタンが表示されます。

  • メモプログラムを実行したところ

    メモプログラムを実行したところ

何か適当なテキストを記述して「保存」ボタンを押します。すると、データファイルにテキストが書き込まれ、次にこのアドレスにアクセスした時にも同じテキストが表示されます。

【プログラムの解説】

それでは、プログラムを確認してみましょう。(*1)の部分ではWebサーバーを起動します。ここでは、ルート「/」にアクセスした時にはreadHandlerを実行し、「保存」ボタンを押した時、つまり、フォームを投稿した時のURI「/w」にアクセスした時にはwriteHandlerが実行されるようにハンドラを登録しました。

プログラムの(*2)の部分では、データファイルを読み込んだ上で、投稿フォームとテキストボックスと保存ボタンを表示します。

ここでは、HTMLを動的に生成してWebブラウザに返すようにしています。ここで生成するHTMLは、URIの「/w」へテキストエディタの内容を送信するWebフォームです。ブラウザのソース表示で見ると分かるのですが、改行を入れて見やすくし、FORM要素だけ抜き出すと、以下のようなHTMLとなります。このうち、textarea要素の表示テキストの部分は、データファイルから読み込んだ内容が表示されます。

<form method='POST' action='/w'>
  <textarea name='text'>ここにメモを記入してください。</textarea>
  <input type='submit' value='保存' />
</form>

そして、(*3)の部分では、上記の投稿フォームから送信された内容を解析して、データファイルに保存する処理となっています。ここでは、投稿されたtextのデータを取り出してファイルへ書き込みます。

投稿されたフォームから任意のフィールドを取り込むのに必要なのが、ParseFormメソッドです。これを実行すると、『Form[フィールド名]』でフォーム内の値を取り出すことができます。取り出した値は、string型のスライスであり、そのフィールドが見当たらない場合、要素数は0となります。

最後に、(*4)の部分では、ルートページへリダイレクトして戻るようにします。つまり、テキストを保存した後に、テキストを読み込んで表示するルートページへ画面遷移するようにすることで、テキストファイルの内容が画面に表示されるという訳です。図にすると、以下のようになります。

  • メモアプリの画面遷移図

    メモアプリの画面遷移図

このように、Webサーバーのアプリを作る際には、画面遷移を考えてプログラムを作ると、よく理解できます。

まとめ

以上、Webサーバーアプリの作成例として、メモアプリを作成してみました。今回のプログラムを起動しておくことで、Webブラウザからローカルにメモを保存できます。また、LAN内で実行する場合には、そのPCのIPアドレスを指定して「http://(PCのIPアドレス):8888」にアクセスします。すると、LAN内でメモを共有することもできます。つまり、手軽に使えるメモ帳サーバーのできあがりです。

前回は10行のプログラムでWebサーバーを作ってみました。今回のプログラムは50行程度です。さすがに、何かしらの機能を持つアプリを作る場合には、それなりの行数が必要になりました。とは言え、Goなら、一度実行ファイルにコンパイルしてしまえば、実行ファイルを別のPCにコピーしただけで動かすことができます。本連載では、今後もサーバー機能を利用した便利なGoの魅力を紹介していきます。

自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2005年IPAスーパークリエイター認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。