Go言語(net/http)でWebサーバーを作成(2)


前回の記事からだいぶ時間が経ってしまいました。
前回の記事はこちらです
本記事では golangでのhttp通信でhtmlファイルの表示をしてみます。

非常に説明が多いです。自分でサンプルコードを理解したのでそれを皆さんに共有できたらと思います。よろしくお願い致します。

今回の記事はあまり有益ではありません。執筆者自身もあまり良い記事だと思っていません。あくまで記録として執筆しました。

こちらのソースコードは書籍「Go言語によるWebアプリケーション開発」に載っています。

package main

import (
    "log"
    "net/http"

    //追加
    "path/filepath"
    "sync"
    "text/template"
)

type templateHandler struct {
    once     sync.Once
    filename string
    templ *template.Template
}


func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    t.once.Do(func() {
        t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
    })

    t.templ.Execute(w, nil)
}

func main() {
    http.Handle("/", &templateHandler{filename: "template1.html"})
    log.Fatal(http.ListenAndServe(":8080", nil))
}

前回に比べてimport部分が増えました。ざっくりではありますが、解説していきます。

path/filepath
・・・ファイルパスを操作します。これによってパス同士の連結や指定をします。

sync
・・・実行を一度だけ行う関数を定義するために必要です。今回はhtmlファイルの読み込みを行う回数を一度にしたいのでこのパッケージを使います。

text/template
・・・htmlを扱うために使用します。最初に紹介した 'prth/filepath' がパス操作ならばこのパッケージはそのパスで指定されたファイルを実際にwebページとして読み込む操作をします。

type templateHandler struct {
    //一度だけ実行する関数を使うため
    once     sync.Once
    filename string
    //ポインタで Templateを使う
    templ *template.Template
}

まずはじめに構造体を定義します。ここでimportしたパッケージ syncを使って一度だけ実行する関数、どのファイルを表示するのか決めるfilename、実際にhtmlファイルを表示するためのtemplateをポインタで作ります。

次に構造体へメソッド(関数)を追加します。構造体にメソッドを追加する時は以下のルールで追加します。

func(任意の変数, 構造体名(ポインタ)) メソッド名(引数){

} 

任意の変数部分は追加する関数内で構造体自身をどのような変数で表現するかを決めることができます。一度ではなかなか理解ができないのでソースコードを読み進めるなかで理解していきます。

func (t *templateHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    t.once.Do(func() {
        t.templ = template.Must(template.ParseFiles(filepath.Join("templates", t.filename)))
    })

    t.templ.Execute(w, nil)
}

それでは追加したメソッドを読んでいきましょう。
前回にご説明した「func handler」を「ServeHTTP」という名前で追加しています。しかし、今回は前回とは少し違い、構造体で onceという名前で宣言したものを使います。 onceにあるメソッド「Do」を使って一度だけ実行する関数を作成していきます。それが

func(){
     t.tmpl = template.Must(template.ParseFiles(filepath.Join("templates", t.filename))
   })
   t.templ.Execute(w, nil)
}

この部分です。t.tmplで構造体templeHandlerにあるtmplにアクセスします。
メソッドを追加する際に(t, *templeHandler)なので「t」なんです。 ここを「s」に変えたならば s.tmplでアクセスします。

template.Mustで絶対に実行するように設定し、template.ParseFilesでfilepath.Joinによって指定されたファイルへアクセスし、読み込みます。そして、最終的に構造体の tmplに格納します。

メソッドの最後は .Evecuteでhttp通信に書き込んでいきます。

それではmain関数を見ていきます。

func main() {
    http.Handle("/", &templateHandler{filename: "template1.html"})
    log.Fatal(http.ListenAndServe(":8080", nil))
}

main関数内は前回ご説明しましたね。
今回は &templeHandlerで要素を{filename:"ファイル名"}で指定します。このファイルはgoスクリプトが保存されているフォルダに「templates」フォルダを作成し、その中に.htmlファイルを保存してください。