本連載は、楽しくGo言語について学ぶ連載です。三回目の今回は、Go言語でWebサーバーを作ってみましょう。Go言語を使えば、10行程度のプログラムで簡易Webサーバーが書けてしまうので紹介します。
一番簡単なWebサーバー
Go言語の標準ライブラリ「net/http」を使うと、Webサーバーが手軽に書けるので便利です。以下は、「Hello, World!」とブラウザに出力するだけのWebサーバーです。コメント混みで10行程度のプログラムですが、しっかりと動きます。
まずは、以下のプログラムを「hello_server.go」という名前で保存しましょう。コメント混みで10行です。
package main
import ("net/http")
func main() { // メイン処理
http.HandleFunc("/", HelloHandler) // ハンドラを登録 --- (*1)
http.ListenAndServe(":8888", nil) // サーバーを起動 --- (*2)
}
// HelloHandler サーバーの処理内容を記述 --- (*3)
func HelloHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!")) // --- (*4)
}
プログラムを実行しましょう。WindowsならPowerShellで、macOSならターミナル.appで以下のコマンドを実行します。
cd (プログラムを保存したフォルダのパス)
go run hello_server.go
続いて、Webブラウザを開いて、「http://localhost:8888」へアクセスしてみましょう。すると、「Hello, World!」と表示されるはずです。
以下、各OSで実行した時の画面です。Windows/macOSを問わず同じプログラムで実行できるところが良いところです。
それでは、簡単にプログラムを紹介します。実際のところ、Webサーバーを起動する処理は、main関数の中で書いている二行のみです。プログラムの(*1)の部分では、Webサーバーにアクセスがあったときに、どんな処理を行うのかを指定します。ここでは、アクセスがあったら、HelloHandlerという関数を実行することを指定します。続く、(*2)の部分でサーバーを起動します。ここでは、ポート番号8888で起動しています。もし、既にポート8888が使用されている場合、ここで指定しているポート番号を変えると良いでしょう。
それから、サーバーにアクセスがあったときの処理を記述しているのが(*3)の部分です。(*4)の部分ではサーバーのレスポンスとして、"Hello, World!"を書き込みます。
このように、10行に満たないプログラムで、簡単なWebサーバーを作ることができました。非常に簡潔でGo言語の良さが生きています。
サイコロサーバーを作ってみよう
ただ「Hello, World!」と表示されるだけのWebサイトなど面白くもありません。今度は、アクセスする度に、異なる値が表示されるようにしてみましょう。例として、アクセスするたびに、異なる数字が表示されるサイコロサーバーを作ってみます。
以下のプログラムを「dice_server.go」という名前で保存しましょう。
package main
import (
"fmt"
"math/rand"
"net/http"
)
func main() {
// サーバーの起動 --- (*1)
http.HandleFunc("/", DiceHandler)
http.ListenAndServe(":8888", nil)
}
// DiceHandler サーバーの処理内容を記述
func DiceHandler(w http.ResponseWriter, r *http.Request) {
// サイコロの目と出力メッセージを生成 --- (*2)
v := rand.Intn(6) + 1
s := fmt.Sprintf("サイコロの目は、%d", v)
// 書き出す --- (*3)
w.Write([]byte(s))
}
そして、コマンドラインで以下のコマンドを実行しましょう。
go run dice_server.go
それから、同様にWebブラウザを起動して「http://localhost:8888」にアクセスします。すると、以下のように、アクセスする度に、異なる値が表示されます。
プログラムを見てみましょう。hello_server.goのプログラムより見やすいですか?そうなんです。さっきのプログラムは10行に詰め込むために、空白を詰めていました。なお、Visual Studio CodeなどのエディタでGo言語を書くと、自動的に読みやすくプログラムを整形してくれます。
プログラムの(*1)の部分では、Webサーバーを起動します。そして、クライアントからアクセスがあったとき、DiceHandler関数が実行されます。(*2)の部分では、アクセスがあったときに実行する処理を記述します。rand.Intn関数を利用して乱数を生成します。そして、出力メッセージを準備して、(*3)の部分で書き出します。
ローカルファイルを自動的に返すようにする
サイコロサーバー程度なら簡単です。とは言え、動的にコンテンツを生成するのではなく、既に用意した静的なHTMLファイルを出力するサーバーも簡単に作れます。
ここでは、「file_server.go」というメインプログラムの他に、pubというフォルダを用意して、そこに「index.html」という適当なHTMLファイルを保存しましょう。フォルダ構造は次のようなものを想定しています。
.
├── file_server.go
└── <pub>フォルダ
└── index.html
なお、index.htmlは次のような簡単なものです。
<html><meta charset="utf-8"><body>
<h1>こんにちは</h1>
</body></html>
そして、肝心のGoのプログラム「file_server.go」は以下のようになります。
package main
import (
"fmt"
"math/rand"
"net/http"
)
func main() {
// 公開するディレクトリを指定する --- (*1)
fs := http.FileServer(http.Dir("pub"))
// サーバーURIとの対応を指定 --- (*2)
http.Handle("/", fs)
// 動的コンテンツの例としてサイコロも実装 --- (*3)
http.HandleFunc("/dice", DiceHandler)
// サーバーの起動 --- (*4)
http.ListenAndServe(":8888", nil)
}
// DiceHandler サイコロを返す
func DiceHandler(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(fmt.Sprintf(
"<h1>サイコロ: %d</h1>", rand.Intn(6)+1)))
}
プログラムを実行するには、以下のコマンドを実行しましょう。
go run file_server.go
そして、Webブラウザを起動して「http://localhost:8888」にアクセスします。すると、HTMLの内容が表示されます。また、「http://localhost:8888/dice」へアクセスすると、先ほど紹介した動的なサイコロも表示されます。
プログラムを確認してみましょう。プログラムの(*1)の部分では、静的なファイルを配置した公開ディレクトリを指定します。そして、(*2)の部分では、(*1)で指定したディレクトリとブラウザのURIとの対応を指定します。ここでは、「/」を指定しており、つまり「http://localhost:8888/」にアクセスがあると、pubディレクトリ以下のファイルを出力します。
また、(*3)の部分では「/dice」にアクセスがあると、サイコロの値をランダムに表示します。動的なコンテンツが必要なければ、この部分を削除しても良いでしょう。
そして、最後に(*4)の部分で実際にWebサーバーを起動します。
まとめ
以上、今回はGo言語でWebサーバーを作成する方法を紹介しました。思ったよりも簡単に、マルチプラットフォーム対応のWebサーバーが作成できました。ちょっとサーバーが必要な場面で手軽に使えます。今後、このGo言語のサーバー機能を利用したプログラムも紹介していきますので、お楽しみに。
ちなみに、Node.jsやPythonなどで動的なスクリプト言語を使えば、同じように短い行数でWebサーバーを作ることができます。しかし、Go言語は動作が高速な静的型付けのコンパイル言語です。コンパイル言語でこれほど手軽に作れるのはGo言語ならではでしょう。
自由型プログラマー。くじらはんどにて、プログラミングの楽しさを伝える活動をしている。代表作に、日本語プログラミング言語「なでしこ」 、テキスト音楽「サクラ」など。2001年オンラインソフト大賞入賞、2004年度未踏ユース スーパークリエータ、2010年 OSS貢献者章受賞。技術書も多く執筆している。