Sorry, This post is Japanese Only.
There is a sample file for singleton WEBserver of Go Language.
If you type URL “http://localhost:8080” on your browser after this file is executed , you can look WEB pages and execute cgi .
さて、サンプルソース。今回は2部構成。
まずはパッケージcgi1のソース。
パッケージはサブルーチンの集まりでライブラリになる部分のことね。クラスと違って、継承や親子関係はないけど、インターフェイスを持つ事が出来て、パッケージ以外に公開できるサブルーチン(GoではGoルーチンとも呼ばれる)を限定する事もできたりする。
インターフェイスの話は今回はしないので、とりあえず、パッケージだけ作った。
package cgi1
import (
"template"
"http"
)
type H struct {
背番号 int
カナ byte
名前 string
住んでる所 string
性格 string
}
func GetHanaaruki(name string) (H,bool) {
oHanaaruki := H{1,'o', "オオハナアルキ", "地上", "ちょっと凶暴"}
mHanaaruki := H{2,'m', "マンモスハナアルキ", "地上", "のんびり"}
dHanaaruki := H{3,'d', "ダンボハナアルキ", "空中", "ぱたぱた系"}
jHanaaruki := H{4,'j', "ジェットハナアルキ", "空中", "ビュンビュン系"}
bHanaaruki := H{5,'b', "バニラ・ランモドキ", "樹上", "お色気派"}
hmap := map[string]H {
"オオハナアルキ":oHanaaruki,
"マンモスハナアルキ":mHanaaruki,
"ダンボハナアルキ":dHanaaruki,
"ジェットハナアルキ":jHanaaruki,
"バニラ・ランモドキ":bHanaaruki }
r,e := hmap[name]
return r,e
}
const tplOK = `
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
<HTML><HEAD>
<meta HTTP-EQUIV = \"Content-Type\" CONTENT = \"text/html; charset=UTF-8\" >
<title>{名前}みっけ!</title>
</HEAD>
<BODY>
<center>
{名前}さんは{住んでる所}に住んでて、{性格}なハナアルキさんだよ
</center>
<br /><hr>produced by Tugu Katagiri. Hanaaruki lover.<br />
</body>
</html>
`
const tplNG = `
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
<HTML><HEAD>
<meta HTTP-EQUIV = \"Content-Type\" CONTENT = \"text/html; charset=UTF-8\" >
<title>{@}なんてないさ!</title>
</HEAD><BODY>
<b>{@}なんて嘘さ!</b>
<br /><hr>produced by Tugu Katagiri. Hanaaruki lover.<br />
</body>
</html>
`
const tplFailure = `
<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0 Transitional//EN\">
<HTML><HEAD>
<meta HTTP-EQUIV = \"Content-Type\" CONTENT = \"text/html; charset=UTF-8\" >
<title>失敗!</title>
</HEAD><BODY>
<b>{@}なんてフィールド、ないよ!</b>
<br /><hr>produced by Tugu Katagiri. Hanaaruki lover.<br />
</body>
</html>
`
func CgiMain(c *http.Conn,req *http.Request) {
// httpパッケージを使ってNameフィールドの値を取得
r := req.FormValue("Name")
// 結果に従って、あらかじめ作っておいたテンプレートを出力
if r != "" {
gh,e := GetHanaaruki(r)
if e{
t := template.MustParse(tplOK, nil);
t.Execute(gh, c);
}else{
t := template.MustParse(tplNG, nil);
t.Execute(r, c);
}
}else{
t := template.MustParse(tplFailure, nil);
t.Execute("NAME", c);
}
}
ちなみに、Funcが関数なんだけど、名前の最初の一文字を大文字にすると、スコープがPublicになる。なので、このパッケージcgi1では、構造体のH、と二つの関数、GetHanaarukiとCgiMainがアクセスできるようになってるの。
内部用のCost値(定数)にはヒアドキュメントも書ける。HTMLコードなので、ブログ対策で<>が全角だから動かす時は半角に戻してね。
さて、じゃ、このcgi1パッケージ、これは何をするパッケージなのか?
Go言語のおさらい~webページ用のCGIを作ってみる
http://blogs.wankuma.com/esten/archive/2010/07/26/191612.aspx
と同じCGIの処理だったりする。
前回はFormの中身を取るのに、デコードとかしたけど、今回は、httpパッケージのRequestにあるFormValue関数を使って取得。簡単になりましたw
そしてTemplateパッケージの登場。最近はやりのテンプレートさんです。テンプレート自身はヒアドキュメントで宣言して、execute関数使って値を引き渡すと、os.Stdoutに適用結果がかえるしくみ。これは覚えておくと便利だよ。
そして、呼び出し側。
package main
import (
"http"
"io"
"cgi1"
)
func formPage(c *http.Conn, req *http.Request) {
const myHtml = `
<HTML>
<BODY>
<form method="get" action="main.cgi">
<INPUT TYPE="TEXT" NAME="Name" value="ダンボハナアルキ">
<INPUT TYPE="submit" VALUE="送信">
</form>
</BODY>
</HTML>
`
io.WriteString(c, myHtml);
}
func maincgiPage(c *http.Conn, req *http.Request) {
cgi1.CgiMain(c,req)
}
func main() {
// HTTPプロトコルで localhost 以下に指示されてくるファイルで分岐
http.Handle("/", http.HandlerFunc(formPage));
http.Handle("/main.cgi", http.HandlerFunc(maincgiPage));
// 8080ポートでListen開始
err := http.ListenAndServe(":8080", nil);
// 失敗してたらパニクって良い
if err != nil { panic("ListenAndServe: ") }
}
自分が作ったcgi1パッケージもimportして、準備。
main関数のポイントは大きく分けて3つ。
- Httpプロトコルから送られてきた情報で、表示するページ処理関数ポインタへの分岐するように設定
- LocalHost:8080のHttpプロトコルまち
- プロトコル待ち失敗したら、パニック(例外処理)になるGoプログラム
このmainは、ローカルホストの8080ポートをhttpプロトコル用に確保して開き、流れてくるプロトコル情報を捕まえて、プログラムに書かれた飛び先へと処理をジャンプして実行する、というものなのね。
いま、/でFormPage関数を、/main.cgiでmaincigipageを実行するように指示してあるから、それに従って操作してみる。それ以外を指定された時の動きの話はここではやらないw またあとでw
コンパイルしたmain.exeを実行しておいて、ウェブブラウザで http://localhost:8080 をタイプ。
ブラウザにページが出てきて
送信ボタンを押してみると、
というわけで、テンプレどおり。
Go言語って、WEBプログラミングをする時、httpパッケージを使って自分でhttpプロトコルを好きに解析してWEBサーバーそのものから作り上げる事がとても簡単にできるんだね。