本連載は、楽しくGo言語について学ぶ連載です。三回目の今回は、Go言語でWebサーバーを作ってみましょう。Go言語を使えば、10行程度のプログラムで簡易Webサーバーが書けてしまうので紹介します。

  • Go言語なら10行で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を問わず同じプログラムで実行できるところが良いところです。

  • WindowsでWebサーバーを実行したところ

    WindowsでWebサーバーを実行したところ

  • macOSでWebサーバーを実行したところ

    macOSでWebサーバーを実行したところ

それでは、簡単にプログラムを紹介します。実際のところ、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年オンラインソフト大賞入賞、2005年IPAスーパークリエイター認定、2010年 OSS貢献者章受賞。技術書も多く執筆している。