LoginSignup
1
2

More than 1 year has passed since last update.

GoでHTML (+ CSS, JavaScript) を表示する

Last updated at Posted at 2022-03-09

問題

Go言語でサーバーを立ち上げてHTMLを表示させる際、cssとjsファイルをHTMLに適用させるのに少し時間がかかりました。
備忘録としてHTML + CSS + JavaScriptのページを表示する方法を記載していきます。

解決方法

結論から言うと、go:embedを使用しました。
下記のテックブログを参考にして、静的ファイルを変数に格納 -> ファイルシステムを取得して読み込むという方法で課題を解決しました。

下記にコードを記載しますが、全てを記載すると記述が多くなるため省略してあります。
全コードが気になる方はgitを確認してください。
https://github.com/Makoto87/test_go_embed

goのバージョン

go version go1.17.3 darwin/amd64

ディレクトリ構成

.
├── go.mod
├── main.go
└── views
    ├── main.html
    ├── scripts
    │   └── textarea.js
    └── styles
        └── stylesheet.css

goファイル

main.go
package main

import (
	"embed"

	"html/template"
	"net/http"
)

// viewsディレクトリ下のファイルを全て変数に格納する
//go:embed views/*
var views embed.FS

// メイン画面の表示
var templates = template.Must(template.ParseFS(views, "views/main.html"))

func viewHandler(w http.ResponseWriter, r *http.Request) {
	if err := templates.ExecuteTemplate(w, "main.html", nil); err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
	}
}

func main() {
	http.HandleFunc("/view/", viewHandler)

	// viewsに格納したファイルを全て公開
	http.Handle("/views/", http.FileServer(http.FS(views)))

	// httpサーバーを立ち上げ
	http.ListenAndServe(":8080", nil)
}

htmlファイル

main.html
<!DOCTYPE html>
<html lang="en">
<head>
      <!-- 前略 -->
      <!-- go:embedで読み込んだviewsディレクトリ下のcssを読込 -->
      <link rel="stylesheet" href="/views/styles/stylesheet.css">
</head>
<body>
      <!-- 前略 -->
      <!-- go:embedで読み込んだviewsディレクトリ下のjsファイルを読込 -->
      <script src="/views/scripts/textarea.js"></script>
</body>
</html>

書いたコードで表示された画面

ちゃんとCSSが適用されています
CSSではtextareaの高さを指定しました
image1

JavaScriptも適用されています
入力した文字に合わせてtextareaが変化するようになっています
image2

解説

embed をインポートし、変数の上に //go:embed views/* という記述をすれば、viewsディレクトリ下のファイルを変数に読み込んでくれます。

embedパッケージについて公式ドキュメントではこう記載されています。

Package embed provides access to files embedded in the running Go program.

Go source files that import "embed" can use the //go:embed directive to initialize a variable of type string, []byte, or FS with the contents of files read from the package directory or subdirectories at compile time.

簡単に訳すと、
embedを使用することで、コンパイル時にパッケージディレクトリまたはサブディレクトリから読み取られたファイルの内容で変数を初期化できる。
という感じの内容になっています。

ファイルを変数に格納した後は、ファイルを読み込めるようにする処理を記述します。それが下記のコードになります

http.Handle("/views/", http.FileServer(http.FS(views)))

このコードによって、
http.FSでviewsをhttp.FileSystemに変換し、
http.FileServerでファイルシステム(views)の内容をHTTPリクエストに返すhandlerを返し、
http.Handleで、httpサーバーが立ち上がった後に、/views/というパスを指定されたらファイルシステムが返されるようになります。
ただしhttp.Handleを使うときは、http.ListenAndServeの第二引数をnilにしておく必要があります。

パスを指定してファイルシステムが返されるようになれば、htmlファイル上でそのパスを活用して、cssファイルとjsファイルを読み込んだHTMLを表示できます。
cssを読み込む場合は下記の記述になります。

<link rel="stylesheet" href="/views/styles/stylesheet.css">

embedで読み込んだファイルはバイナリにも埋め込まれるというメリットがあります。
これによって、ビルド時のディレクトリ構成とは異なる構成になったとしても、影響を受けずに正常に静的ファイルを返すことができます。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2