Merge pull request #374 from ernix/ja
Translate delta commits into Japanese
This commit is contained in:
15
ja/README.md
15
ja/README.md
@@ -1,4 +1,12 @@
|
||||
# "Go Web プログラミング"
|
||||
この本には現在いくつかのバージョンがあります:
|
||||
|
||||
[中国語で読み始める](<https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/preface.md>)
|
||||
|
||||
[日本語で読み始める](<https://github.com/astaxie/build-web-application-with-golang/blob/master/ja/ebook/preface.md>)
|
||||
|
||||
[English Version](<https://github.com/astaxie/build-web-application-with-golang/blob/master/en/eBook/preface.md>)
|
||||
|
||||
現在この本はすでに出版されています。もし悪くない内容だと思ったら以下より購入することができます。ご協力に感謝いたします:
|
||||
|
||||
- [chinapub](http://product.china-pub.com/3767290)
|
||||
@@ -11,16 +19,17 @@
|
||||
# カンパでサポートする
|
||||
もし"Go Webプログラミング"を気に入っていただけたのなら、寄付を通じて作者にこの本の続きを更新させるか、もっと面白くてためになるオープンソースアプリケーションの開発をご検討下さい:例えばこの本にパッチをあてたり、もっと面白い章を追加したり、もっともっと凄い内容の次回作を出してみたり、beegoを改修してくれたり、です。
|
||||
|
||||
寄付はこちら: [https://me.alipay.com/astaxie](https://me.alipay.com/astaxie)
|
||||
支付宝扫描捐款: 
|
||||
|
||||
English Donate:[donate](http://beego.me/donate)
|
||||
|
||||
## 連絡方法
|
||||
ぜひQQ群にどうぞ:259316004 《Go Web编程》专用交流群
|
||||
|
||||
掲示板:[http://bbs.mygolang.com](http://bbs.mygolang.com)
|
||||
掲示板:[http://bbs.go-china.org/](http://bbs.go-china.org/)
|
||||
|
||||
## 謝辞
|
||||
まずGolang-ChinaのQQ群102319854に感謝を申し上げます。彼らはみんな非常に熱心で、特に数名の方には本当に感謝しています。
|
||||
まずGolang-ChinaのQQ群102319854(すでに満員です)に感謝を申し上げます。2群(384414723)を追加してください。彼らはみんな非常に熱心で、特に数名の方には本当に感謝しています。
|
||||
|
||||
- [四月份平民](https://plus.google.com/110445767383269817959) (コードレビュー)
|
||||
- [Hong Ruiqi](https://github.com/hongruiqi) (コードレビュー)
|
||||
|
||||
@@ -96,13 +96,16 @@ PATHを設定します。`export PATH=$PATH:$GO_INSTALL_DIR/go/bin`
|
||||
|
||||
もしgoのUsage情報が現れた場合は、goはすでにインストールされています。もしこのコマンドが存在しないと出てきた場合は、自分のPATH環境変数の中にgoのインストールディレクトリが含まれているか確認してください。
|
||||
|
||||
### Windows インストール
|
||||
### Windows インストール ###
|
||||
|
||||
[ダウンロードURL][downlink]に接続し、32bitシステムはgo1.0.3.windows-386.msiをダウンロードします。64bitシステムであればgo1.0.3.windows-amd64.msiをダウンロードします。ファイルをダブルクリックして、デフォルトのまま「次へ」をクリックします。この時goはすでにあなたのシステムにインストールされています。デフォルトでインストール後の環境変数には`c:/go/bin`が追加されています。cmdを開いて、`go`と入力します。
|
||||
[Google Code ダウンロードページ][downlink]に接続し、32bit の場合は名前に windows-386 を含む msi パッケージをダウンロードします。64bit であれば名前に windows-amd64 を含むものをダウンロードします。ダウンロード後実行しますが、デフォルトのインストールフォルダである C:\Go\を変更してはいけません。他の場所にインストールしてしまうと、あなたが書いた Go コードが実行できなくなってしまうかもしれません。インストールが終わるとデフォルトで環境変数 Path に Go のインストールフォルダの下にある bin フォルダ `C:\Go\bin\` が追加され、Go のインストールフォルダである `C:\Go\` の値が環境変数 GOROOT に追加されます。
|
||||
|
||||
macインストール成功の画像で、インストールが成功します。
|
||||
** インストールが成功しているか確認する **
|
||||
|
||||
「ファイル名を指定して実行」に `cmd` を入力することでコマンドラインツールを開きます。プロンプトで`go`と入力することで Usage 情報が確認できるか確かめることができます。`cd %GOROOT%` を入力すると、Go のインストールフォルダに入れるか確認できます。どちらも成功していれば、インストールに成功しています。
|
||||
|
||||
インストールに成功していなければ、環境変数 Path と GOROOT の値を確認してください。もし存在しなければアンインストールの上再インストールし、存在していればコンピュータを再起動し、上の手順を再度お試しください。
|
||||
|
||||
もしGoのUsage情報が現れたら、Goはすでにインストールされています。もしこのコマンドが存在しないと出た場合は自分のPATH環境変数にGoのインストールディレクトリが含まれるか確認してください。
|
||||
|
||||
## サードパーティツールのインストール
|
||||
### GVM
|
||||
|
||||
@@ -33,7 +33,7 @@
|
||||
array_windows.go
|
||||
array_freebsd.go
|
||||
|
||||
`go build`の際、システム名の末尾のファイルから選択的にコンパイルすることができます(linux、darwin、windows、freebsd)
|
||||
`go build`の際、システム名の末尾のファイルから選択的にコンパイルすることができます(Linux、Darwin、Windows、Freebsd)
|
||||
|
||||
## go clean
|
||||
|
||||
|
||||
@@ -166,7 +166,7 @@
|
||||
"env": { "GOPATH": "$HOME/golang:$GS_GOPATH" }
|
||||
}
|
||||
|
||||
`$GS_GOPATH` は gosublime の仮想的な環境変数です。自動的に`.go`ファイルが存在する `~/go/src` を探し出すことで、 `~/go/` をプロジェクトのパスと推測し、自動的に `GOPATH` を適用します。
|
||||
`$GS_GOPATH` は gosublime の仮想的な環境変数です。自動的に`.go`ファイルが存在する `~/go/src` を探し出すことで、 `~/go/` をプロジェクトのパスと推測し、自動的に `GOPATH` を適用します。(注意:このような方法ではsublimeにおいてオリジナルのGOPATHを上書きしてしまいます。もしこの設定でエラーが発生した場合は、GOPATHに関連した問題が発生していることになります)
|
||||
|
||||
もうひとつは、sublime プロジェクトの保存です。 project_name.sublime-project を修正して項目を追加します
|
||||
|
||||
@@ -226,7 +226,7 @@ Vimはviから発展したテキストエディタです。コード補完、コ
|
||||
|
||||
5. おめでとうございます。インストール完了です。あなたは今から`:e main.go`でGoで開発する面白さを体験することができます。
|
||||
|
||||
より多くのVIM 設定は、[リンク](http://monnand.me/p/vim-golang-environment/zhCN/)をご参照ください。
|
||||
より多くのVIMの設定は、[リンク](http://monnand.me/p/vim-golang-environment/zhCN/)をご参照ください。
|
||||
|
||||
## Emacs
|
||||
Emacsは伝説の神器です。彼女はエディタであるだけでなく、統合環境でもあります。または開発環境の集大成と呼んでもよいかもしれません。これらの機能はユーザの身を万能のオペレーティングシステムに置きます。
|
||||
|
||||
@@ -103,7 +103,7 @@ Goではbool値の型は`bool`です。値は`true`もしくは`false`です。
|
||||
|
||||
>注意しなければならないのは、これらの型の変数間は相互に代入または操作を行うことができないということです。コンパイル時にコンパイラはエラーを発生させます。
|
||||
>
|
||||
>下のコードはエラーが発生します。
|
||||
>下のコードはエラーが発生します。:invalid operation: a + b (mismatched types int8 and int32)
|
||||
>
|
||||
>> var a int8
|
||||
|
||||
@@ -135,7 +135,7 @@ Goではbool値の型は`bool`です。値は`true`もしくは`false`です。
|
||||
frenchHello = "Bonjour" // 通常の代入
|
||||
}
|
||||
|
||||
Goの文字列は変更することができません。例えば下のコードはコンパイル時にエラーが発生します。
|
||||
Goの文字列は変更することができません。例えば下のコードはコンパイル時にエラーが発生します。:cannot assign to s[0]
|
||||
|
||||
var s string = "hello"
|
||||
s[0] = 'c'
|
||||
@@ -168,7 +168,10 @@ Goでは`+`演算子を使って文字列を連結することができます:
|
||||
m := `hello
|
||||
world`
|
||||
|
||||
`` ` `` で括られた文字列はRaw文字列です。すなわち、文字列はコード内の形式がそのままプリント時の形式になります。文字列の変更はありません。改行はそのまま出力されます。
|
||||
`` ` `` で括られた文字列はRaw文字列です。すなわち、文字列はコード内の形式がそのままプリント時の形式になります。文字列の変更はありません。改行はそのまま出力されます。例えばこの例では以下のように出力されます:
|
||||
|
||||
hello
|
||||
world
|
||||
|
||||
### エラー型
|
||||
Goにはビルトインの`error`型があります。専らエラー情報の処理に使用されます。Goの`package`の中にはエラー処理を行う`errors`というパッケージがあります。
|
||||
@@ -383,7 +386,7 @@ sliceには便利な操作があります
|
||||
下のコードをご覧ください。`map`の読み込みと代入は`slice`と似ています。`key`を通して操作します。ただ、`slice`の`index`は`int`型のみになります。`map`には多くの型があります。`int`でもかまいませんし、`string`や`==`と`!=`演算子が定義されている全ての型でもかまいません。
|
||||
|
||||
// keyを文字列で宣言します。値はintとなるディクショナリです。この方法は使用される前にmakeで初期化される必要があります。
|
||||
var numbers map[string] int
|
||||
var numbers map[string]int
|
||||
// もうひとつのmapの宣言方法
|
||||
numbers := make(map[string]int)
|
||||
numbers["one"] = 1 //代入
|
||||
@@ -407,7 +410,7 @@ mapを使う段階で注意しなければならないことがいくつかあ
|
||||
`delete`で`map`の要素を削除します:
|
||||
|
||||
// ディクショナリを初期化します。
|
||||
rating := map[string]float32 {"C":5, "Go":4.5, "Python":4.5, "C++":2 }
|
||||
rating := map[string]float32{"C":5, "Go":4.5, "Python":4.5, "C++":2 }
|
||||
// mapは2つの戻り値があります。2つ目の戻り値では、もしkeyが存在しなければ、okはfalseに、存在すればokはtrueになります。
|
||||
csharpRating, ok := rating["C#"]
|
||||
if ok {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# 2.3 フローと関数
|
||||
この節ではGoの中のフロー制御と関数操作についてご紹介します。
|
||||
## フロー制御
|
||||
フロー制御はプログラム言語の中の最も偉大な発明です。なぜならこれがあるだけで、あなたはとても簡単なフローの記述でとても複雑なロジックを表現できるからです。フロー制御は3つの部分から成ります:条件判断、ループ制御及び無条件ジャンプです。
|
||||
フロー制御はプログラム言語の中の最も偉大な発明です。なぜならこれがあるだけで、あなたはとても簡単なフローの記述でとても複雑なロジックを表現できるからです。Goではフロー制御は3つの部分から成ります:条件判断、ループ制御及び無条件ジャンプです。
|
||||
### if
|
||||
`if`はあらゆるプログラミング言語の中で最もよく見かけるものかもしれません。この文法は大雑把に言えば:もし条件を満足しなければ何々を行い、そうでなければまたもう一つ別のことをやるということです。
|
||||
|
||||
@@ -468,7 +468,7 @@ Goのコードを書いている時は、importコマンドによってパッケ
|
||||
|
||||
fmt.Println("hello world")
|
||||
|
||||
上のfmtはGo言語の標準ライブラリです。実はgorootの下にこのモジュールが加えられています。当然Goのインポートは以下のような2つの方法で自分の書いたモジュールを追加することができます:
|
||||
上のfmtはGo言語の標準ライブラリです。実は`GOROOT`環境変数で指定されたディレクトリの下にこのモジュールが加えられています。当然Goのインポートは以下のような2つの方法で自分の書いたモジュールを追加することができます:
|
||||
|
||||
1. 相対パス
|
||||
|
||||
|
||||
@@ -156,7 +156,7 @@ methodはstructの上でしか使用されないのでしょうか?当然違
|
||||
b.color = c
|
||||
}
|
||||
|
||||
func (bl BoxList) BiggestsColor() Color {
|
||||
func (bl BoxList) BiggestColor() Color {
|
||||
v := 0.00
|
||||
k := Color(WHITE)
|
||||
for _, b := range bl {
|
||||
@@ -192,13 +192,13 @@ methodはstructの上でしか使用されないのでしょうか?当然違
|
||||
fmt.Printf("We have %d boxes in our set\n", len(boxes))
|
||||
fmt.Println("The volume of the first one is", boxes[0].Volume(), "cm³")
|
||||
fmt.Println("The color of the last one is",boxes[len(boxes)-1].color.String())
|
||||
fmt.Println("The biggest one is", boxes.BiggestsColor().String())
|
||||
fmt.Println("The biggest one is", boxes.BiggestColor().String())
|
||||
|
||||
fmt.Println("Let's paint them all black")
|
||||
boxes.PaintItBlack()
|
||||
fmt.Println("The color of the second one is", boxes[1].color.String())
|
||||
|
||||
fmt.Println("Obviously, now, the biggest one is", boxes.BiggestsColor().String())
|
||||
fmt.Println("Obviously, now, the biggest one is", boxes.BiggestColor().String())
|
||||
}
|
||||
|
||||
上のコードはconstでいくつかの定数を定義しています。その後カスタム定義型を定義しています。
|
||||
@@ -209,9 +209,9 @@ methodはstructの上でしか使用されないのでしょうか?当然違
|
||||
|
||||
次に上のカスタム定義型をレシーバとしてmethodを定義します。
|
||||
|
||||
- Volume()はレシーバをBoxとして定義します。Boxの堆積を返します。
|
||||
- Volume()はレシーバをBoxとして定義します。Boxの体積を返します。
|
||||
- SetColor(c Color)はBoxの色をcに変更します。
|
||||
- BiggestsColor()はBoxListに定義されており、listの中の体積が最大の色を返します。
|
||||
- BiggestColor()はBoxListに定義されており、listの中の体積が最大の色を返します。
|
||||
- PaintItBlack()はBoxListのすべてのBoxの色を全部黒に変更します。
|
||||
- String()はColorに定義されており、Colorの具体的な色を返します(文字列形式)
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ mは3つの型を持つことのできるオブジェクトなので、Men型
|
||||
mike := Student{Human{"Mike", 25, "222-222-XXX"}, "MIT", 0.00}
|
||||
paul := Student{Human{"Paul", 26, "111-222-XXX"}, "Harvard", 100}
|
||||
sam := Employee{Human{"Sam", 36, "444-222-XXX"}, "Golang Inc.", 1000}
|
||||
Tom := Employee{Human{"Sam", 36, "444-222-XXX"}, "Things Ltd.", 5000}
|
||||
Tom := Employee{Human{"Tom", 37, "222-444-XXX"}, "Things Ltd.", 5000}
|
||||
|
||||
//Men型の変数iを定義します。
|
||||
var i Men
|
||||
@@ -354,7 +354,7 @@ sort.Interfaceは実は組み込みフィールドです。sort.Interfaceのす
|
||||
}
|
||||
|
||||
### リフレクション
|
||||
Goはリフレクションを実装しています。いわゆるリフレクションとは動的な実行時の状態です。私達が一般的に使用しているパッケージはreflectパッケージです。どのようにreflectパッケージを使うかはオフィシャルのドキュメントに詳細な原理が説明されています。[laws of reflection](http://golang.org/doc/articles/laws_of_reflection.html)
|
||||
Goはリフレクションを実装しています。リフレクションはプログラムの実行時の状態を検査することができます。私達が一般的に使用しているパッケージはreflectパッケージです。どのようにreflectパッケージを使うかはオフィシャルのドキュメントに詳細な原理が説明されています。[laws of reflection](http://golang.org/doc/articles/laws_of_reflection.html)
|
||||
|
||||
reflectを使うには3つのステップに分けられます。下で簡単にご説明します:リフレクションは型の値(これらの値はすべて空のインターフェースを実装しています。)。まずこれをreflectオブジェクトに変換する必要があります(reflect.Typeまたはreflect.Valueです。異なる状況によって異なる関数をコールします。)この2つを取得する方法は:
|
||||
|
||||
|
||||
@@ -31,16 +31,16 @@ goroutineはGoのruntime管理を利用したスレッドコントローラで
|
||||
say("hello") //現在のGoroutines実行
|
||||
}
|
||||
|
||||
出力:
|
||||
hello
|
||||
world
|
||||
hello
|
||||
world
|
||||
hello
|
||||
world
|
||||
hello
|
||||
world
|
||||
hello
|
||||
// 上のプログラムを実行すると以下のように出力されます:
|
||||
// hello
|
||||
// world
|
||||
// hello
|
||||
// world
|
||||
// hello
|
||||
// world
|
||||
// hello
|
||||
// world
|
||||
// hello
|
||||
|
||||
goキーワードで非常に簡単にマルチスレッドプログラミングを実現することがお分かりいただけるかと思います。
|
||||
上の複数のgoroutineは同じプロセスで実行されています。メモリのデータを共有しますが、デザイン上共有を利用して通信を行ったりせず、通信によって共有を行うようにしましょう。
|
||||
@@ -137,7 +137,7 @@ channelは`<-`演算子を使ってデータを送ったり受けたりします
|
||||
}
|
||||
}
|
||||
|
||||
`for i := range c`でこのchannelがクローズを明示されるまで連続してchannelの中のデータを読み込むことができます。上のコードでchannelのクローズが明示されているのが確認できるかと思います。生産者はキーワード`close`関数によってchannelを閉じます。channelを閉じた後はいかなるデータも送信することはできません。消費側は`v, ok := <-ch`という式でchannelがすでに閉じられているかテストすることができます。もしokにfalseが返ってきたら、channelはすでにどのようなデータも無く、閉じられているということになります。
|
||||
`for i := range c`でこのchannelがクローズを明示されるまで連続してchannelの中のデータを読み込むことができます。上のコードでchannelのクローズが明示されているのが確認できるかと思います。生産者は`close`ビルトイン関数によってchannelを閉じます。channelを閉じた後はいかなるデータも送信することはできません。消費側は`v, ok := <-ch`という式でchannelがすでに閉じられているかテストすることができます。もしokにfalseが返ってきたら、channelはすでにどのようなデータも無く、閉じられているということになります。
|
||||
|
||||
>生産者の方でchannelが閉じられる事に注意してください。消費側ではありません。これは容易にpanicを引き起こします。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# 3 Webの基礎
|
||||
|
||||
Webのプログラミングの基礎を勉強することはあなたにとってまさにこの本を読む理由でしょう。事実、どのようにGoを使ってWebアプリケーションをプログラムするかはこの本の目的でもあります。前回までで、Goは既に成熟したHttp処理パッケージを持つことをご紹介しました。これによってどのような事情の動的なWebプログラミングも簡単に作成できます。これ以降の章でご紹介する内容はどれもWebプログラミングの範疇です。この章ではWebに関する概念とGo言語がいかにWebプログラムを実行するかに集中して討論します。
|
||||
Webのプログラミングの基礎を勉強することはあなたにとってまさにこの本を読む理由でしょう。事実、どのようにGoを使ってWebアプリケーションをプログラムするかはこの本の目的でもあります。前回までで、Goは既に成熟したHTTP処理パッケージを持つことをご紹介しました。これによってどのような事情の動的なWebプログラミングも簡単に作成できます。これ以降の章でご紹介する内容はどれもWebプログラミングの範疇です。この章ではWebに関する概念とGo言語がいかにWebプログラムを実行するかに集中して討論します。
|
||||
|
||||
## 目次
|
||||

|
||||
@@ -8,4 +8,4 @@ Webのプログラミングの基礎を勉強することはあなたにとっ
|
||||
## links
|
||||
* [目次](<preface.md>)
|
||||
* 前へ: [第二章まとめ](<02.8.md>)
|
||||
* 次へ: [webでの作業方法](<03.1.md>)
|
||||
* 次へ: [Webでの作業方法](<03.1.md>)
|
||||
|
||||
@@ -85,6 +85,8 @@ HTTPプロトコルはステートレスです。同じクライアントの前
|
||||
//空行、リクエストヘッダとボディを分けるために使われます。
|
||||
//ボディ、リソースへのリクエストのオプション、例えばPOSTが渡すオプション
|
||||
|
||||
HTTPプロトコルはサーバに対して交互にリクエストを送る方法が定義されています。基本は四種類。GET,POST,PUT,DELETEです。ひとつのURLアドレスはひとつのネットワーク上のリソースを描写しています。またHTTPの中のGET, POST, PUT, DELETEはこのリソースの検索、修正、増加、削除の4つの操作に対応しています。よく見かけるのはGETとPOSTです。GETは一般的にリソースの情報を取得/検索するために用いられ、POSTはリソース情報を更新するために用いられます。
|
||||
|
||||
fiddlerパケットキャプチャを通して下のようなリクエスト情報を見ることができます。
|
||||
|
||||

|
||||
@@ -95,13 +97,12 @@ fiddlerパケットキャプチャを通して下のようなリクエスト情
|
||||
|
||||
図3.5 fiddlerがキャプチャしたPOST情報
|
||||
|
||||
**GETリクエストのボディが空であることがわかります。POSTリクエストにはボディがあります**。
|
||||
|
||||
HTTPプロトコルはサーバに対して交互にリクエストを送る方法が定義されています。基本は四種類。GET,POST,PUT,DELETEです。ひとつのURLアドレスはひとつのネットワーク上のリソースを描写しています。またHTTPの中のGET, POST, PUT, DELETEはこのリソースの検索、修正、増加、削除の4つの操作に対応しています。よく見かけるのはGETとPOSTです。GETは一般的にリソースの情報を取得/検索するために用いられ、POSTはリソース情報を更新するために用いられます。
|
||||
GETとPOSTの区別を見てみましょう。
|
||||
1. GETが入力するデータはURLの後に置かれます。?によってURLと渡すデータを分割します。オプションの間は&で繋ぎます。例えばEditPosts.aspx?name=test1&id=12345。POSTメソッドは入力するデータをHTTPパケットのBodyの中に置きます。
|
||||
2. GETが入力するデータの大きさには制限があります。(ブラウザのURLに対する長に制限があるためです。)またPOSTメソッドで入力するデータには制限がありません。
|
||||
3. GETメソッドで入力されたデータはセキュリティの問題を引き起こします。例えばログイン画面があったとして、GETメソッドでデータを入力した場合、ユーザ名とパスワードはURL上にあらわれてしまうことになります。もしページがバッファリングされていたり他の人によっがこのマシンにアクセスすることができれば、ヒストリログからこのユーザのアカウントとパスワードを取得することができてしまいます。
|
||||
|
||||
1. GETリクエストのボディが空であることがわかります。POSTリクエストにはボディがあります。
|
||||
2. GETが入力するデータはURLの後に置かれます。?によってURLと渡すデータを分割します。オプションの間は&で繋ぎます。例えばEditPosts.aspx?name=test1&id=12345。POSTメソッドは入力するデータをHTTPパケットのBodyの中に置きます。
|
||||
3. GETが入力するデータの大きさには制限があります。(ブラウザのURLに対する長に制限があるためです。)またPOSTメソッドで入力するデータには制限がありません。
|
||||
4. GETメソッドで入力されたデータはセキュリティの問題を引き起こします。例えばログイン画面があったとして、GETメソッドでデータを入力した場合、ユーザ名とパスワードはURL上にあらわれてしまうことになります。もしページがバッファリングされていたり他の人によっがこのマシンにアクセスすることができれば、ヒストリログからこのユーザのアカウントとパスワードを取得することができてしまいます。
|
||||
|
||||
### HTTPレスポンスパケット(サーバ情報)
|
||||
HTTPのresponseパケットを見てみることにしましょう。構造は以下のとおりです:
|
||||
@@ -156,4 +157,4 @@ Keep-Aliveは永久にコネクションを保持するものではありませ
|
||||
## links
|
||||
* [目次](<preface.md>)
|
||||
* 前へ: [Webの基礎](<03.0.md>)
|
||||
* 次へ: [GOでwebサーバを建てる](<03.2.md>)
|
||||
* 次へ: [GOでWebサーバを建てる](<03.2.md>)
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 3.2 GOで簡単なwebサーバを立てる
|
||||
# 3.2 Goで簡単なWebサーバを立てる
|
||||
|
||||
前の節でWebはHTTPプロトコルに基づいたサービスであるとご紹介しました。Go言語では完全なnet/httpパッケージを提供しています。httpパッケージを通して実行できるwebサービスを非常に簡単に立ち上げる事ができます。同時にこのパッケージを使用することで、簡単にwebのルーティング、静的なファイル、テンプレート、cookie等のデータに対して設定と操作を行うことができます。
|
||||
前の節でWebはhttpプロトコルに基づいたサービスであるとご紹介しました。Go言語では完全なnet/httpパッケージを提供しています。httpパッケージを通して実行できるWebサービスを非常に簡単に立ち上げる事ができます。同時にこのパッケージを使用することで、簡単にWebのルーティング、静的なファイル、テンプレート、cookie等のデータに対して設定と操作を行うことができます。
|
||||
|
||||
## httpパッケージでwebサーバを立てる
|
||||
## httpパッケージでWebサーバを立てる
|
||||
|
||||
package main
|
||||
|
||||
@@ -50,15 +50,15 @@
|
||||
|
||||
図3.8 ユーザがWebにアクセスしてサーバが出力する情報
|
||||
|
||||
上のコードでwebサーバを書くためにはhttpパッケージの2つの関数を呼ぶだけで良いことがわかります。
|
||||
上のコードでWebサーバを書くためにはhttpパッケージの2つの関数を呼ぶだけで良いことがわかります。
|
||||
|
||||
>もしあなたが以前PHPプログラマであれば。こう問うかもしれません。我々のnginx、apacheサーバは必要ないのですかと?なぜならこいつは直接tcpポートを関ししますので、nginxがsやることをやってくれます。またsayhelloNameは実は我々が書いたロジック関数ですので、phpの中のコントローラ(controller)関数に近いものです。
|
||||
|
||||
>もしあなたがpythonプログラマであったのなら、tornadoを聞いたことがあると思います。このコードはそれとよく似ていませんか?ええ、その通りです。goはpythonのような動的な言語によく似た特性を持っています。webアプリケーションを書くにはとても便利です。
|
||||
>もしあなたがPythonプログラマであったのなら、tornadoを聞いたことがあると思います。このコードはそれとよく似ていませんか?ええ、その通りです。GoはPythonのような動的な言語によく似た特性を持っています。Webアプリケーションを書くにはとても便利です。
|
||||
|
||||
>もしあなたがrubyプログラマであったのなら、RORの/script/serverを起動したのと少し似ている事に気づいたかもしれません。
|
||||
>もしあなたがRubyプログラマであったのなら、RORの/script/serverを起動したのと少し似ている事に気づいたかもしれません。
|
||||
|
||||
Goを通じて簡単な数行のコードでwebサーバを立ち上げることができました。さらにこのWebサーバの内部ではマルチスレッドの特性をサポートしています。続く2つの節でgoが以下にWebのマルチスレッドを実現しているのか細かくご紹介します。
|
||||
Goを通じて簡単な数行のコードでwebサーバを立ち上げることができました。さらにこのWebサーバの内部ではマルチスレッドの特性をサポートしています。続く2つの節でGoが以下にWebのマルチスレッドを実現しているのか細かくご紹介します。
|
||||
|
||||
## links
|
||||
* [目次](<preface.md>)
|
||||
|
||||
@@ -41,7 +41,7 @@ Goがクライアントのリクエストを待ち受けるには以下のよう
|
||||
ServeHTTP(ResponseWriter, *Request) // ルーティング実現器
|
||||
}
|
||||
|
||||
Handlerはインターフェースですが、前の節の中で`sayhelloName`関数が特にServerHTTPというインターフェースを実装してはいませんでした。どうして追加できるのでしょうか?もともとhttpパッケージの中では`HandlerFunc`という型を定義しています。この型はデフォルトでServerHTTPインターフェースを実装しています。つまり、HandlerFunc(f)をコールして強制的にfをHandlerFunc型に型変換しているのです。このようにしてfはServerHTTPメソッドを持つことになります。
|
||||
Handlerはインターフェースですが、前の節の中の`sayhelloName`関数では特にServeHTTPというインターフェースを実装してはいませんでした。どうして追加できるのでしょうか?もともとhttpパッケージの中では`HandlerFunc`という型が定義されています。私達が定義した`sayhelloName`関数はまさにこのHandlerFuncがコールされた結果であり、この型はデフォルトでServeHTTPインターフェースを実装していることになります。つまり、HandlerFunc(f)をコールして強制的にfをHandlerFunc型に型変換しているのです。このようにしてfはServeHTTPメソッドを持つようになります。
|
||||
|
||||
type HandlerFunc func(ResponseWriter, *Request)
|
||||
|
||||
@@ -50,7 +50,7 @@ Handlerはインターフェースですが、前の節の中で`sayhelloName`
|
||||
f(w, r)
|
||||
}
|
||||
|
||||
ルータでは対応するルーティングルールを保存した後、具体的にはどのようにリクエストを振り分けているのでしょうか?以下のコードをご覧ください。デフォルトのルータは`ServerHTTP`を実装します:
|
||||
ルータでは対応するルーティングルールを保存した後、具体的にはどのようにリクエストを振り分けているのでしょうか?以下のコードをご覧ください。デフォルトのルータは`ServeHTTP`を実装します:
|
||||
|
||||
func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
|
||||
if r.RequestURI == "*" {
|
||||
@@ -62,7 +62,7 @@ Handlerはインターフェースですが、前の節の中で`sayhelloName`
|
||||
h.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
上に示す通りルータはリクエストを受け取った後、`*`であれば接続を切断し、そうでなければ`mux.handler(r).ServerHTTP(w, r)`をコールして対応する設定された処理Handlerを返し、`h.ServeHTTP(w, r)`を実行します。
|
||||
上に示す通りルータはリクエストを受け取った後、`*`であれば接続を切断し、そうでなければ`mux.handler(r).ServeHTTP(w, r)`をコールして対応する設定された処理Handlerを返し、`h.ServeHTTP(w, r)`を実行します。
|
||||
|
||||
つまり、目的のルーティングのhandlerのServerHTTPインターフェースへのコールです。ではmux.Handler(r)はどのように処理するのでしょうか?
|
||||
|
||||
@@ -93,9 +93,9 @@ Handlerはインターフェースですが、前の節の中で`sayhelloName`
|
||||
return
|
||||
}
|
||||
|
||||
もともとこれはユーザのリクエストしたURLとルータの中に保存されているmapのマッチングに従って、このhandlerのServHTTPインターフェースをコールすることで目的の関数を実行することができます。
|
||||
もともとこれはユーザのリクエストしたURLとルータの中に保存されているmapに従ってマッチングしています。マッチングによって保存されているhandlerが返されるにあたり、このhandlerのServeHTTPインターフェースがコールされ、目的の関数を実行することができます。
|
||||
|
||||
上の紹介を通じて、ルーティングの全体プロセスを理解しました。これはHandlerインターフェースです。つまり外部のルータはHandlerインターフェースを実装するだけで良く、自分自身で実装したルータのServHTTPの中でカスタムに定義されたルータ機能を実現することができます。
|
||||
上の紹介を通して、私達はルーティングの全体プロセスを理解しました。Goは実は外部で実装されたルータをサポートしています。`ListenAndServe`の第2引数が外部のルータを設定する為に用いられます。これはHandlerインターフェースのひとつで、外部ルータでHandlerインターフェースを実装し、そのServeHTTPにカスタム定義のルーティング機能を実装することができます。
|
||||
|
||||
下のコードを通して、自分自身で簡単なルータを実装してみます。
|
||||
|
||||
@@ -135,11 +135,11 @@ httpパッケージへの分析を通して、全体のコードの実行プロ
|
||||
|
||||
順序にしたがっていくつかの事を行います:
|
||||
|
||||
1 DefaultServerMuxのHandlerFuncをコールする。
|
||||
1 DefaultServeMuxのHandlerFuncをコールする。
|
||||
|
||||
2 DefaultServerMuxのHandleをコールする。
|
||||
2 DefaultServeMuxのHandleをコールする。
|
||||
|
||||
3 DefaultServerMuxのmap[string]muxEntryで目的のhandlerとルーティングルールを追加する。
|
||||
3 DefaultServeMuxのmap[string]muxEntryで目的のhandlerとルーティングルールを追加する。
|
||||
|
||||
- 次にhttp.ListenAndServe(":9090", nil)をコールする。
|
||||
|
||||
@@ -161,7 +161,7 @@ httpパッケージへの分析を通して、全体のコードの実行プロ
|
||||
|
||||
8 handlerのServeHttpをコールする
|
||||
|
||||
9 この例の中では、この後DefaultServerMux.ServeHttpの中に入ります
|
||||
9 この例の中では、この後DefaultServeMux.ServeHttpの中に入ります
|
||||
|
||||
10 requestに従ってhandlerを選択し、このhandlerのServeHTTPに入ります
|
||||
|
||||
|
||||
@@ -39,9 +39,9 @@ Webアプリケーションを書く時は主に2つの方面のデータ検
|
||||
>Goの正規表現の実装は[RE2](http://code.google.com/p/re2/wiki/Syntax)です。すべての文字はUTF-8エンコーディングです。
|
||||
|
||||
## 中国語
|
||||
フォームの要素からユーザの中国語名を得たい場合で、なおかつ正しい中国語であることを保証したい場合、検証を行う必要があります。ユーザに自由に入力はさせません。中国語に対する有効な検証方法は今のところ正規表現しかありません。下のコードをご確認ください
|
||||
フォームの要素からユーザの中国語名を得たい場合で、なおかつ正しい中国語であることを保証したい場合、検証を行う必要があります。ユーザに自由に入力はさせません。中国語に対する有効な検証には、`unicode` パッケージが提供する `func Is(rangeTab *RangeTable, r rune) bool` と正規表現を使う方法があります。下のコードをご確認ください
|
||||
|
||||
if m, _ := regexp.MatchString("^[\\x{4e00}-\\x{9fa5}]+$", r.Form.Get("realname")); !m {
|
||||
if m, _ := regexp.MatchString("^\\p{Han}+$", r.Form.Get("realname")); !m {
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
@@ -113,7 +113,8 @@
|
||||
fmt.Println("error opening file")
|
||||
return err
|
||||
}
|
||||
|
||||
defer fh.Close()
|
||||
|
||||
//iocopy
|
||||
_, err = io.Copy(fileWriter, fh)
|
||||
if err != nil {
|
||||
|
||||
@@ -5,6 +5,8 @@ Goはどのようなデータベースの使用もbuiltinではサポートさ
|
||||
|
||||
現在NOSQLはすでにWeb開発の流行となっています。多くのアプリケーションがNOSQLをデータベースとして採用しています。以前のキャッシュではありません。5.6節ではMongoDBとRedisの2つのNOSQLデータベースについてご紹介します。
|
||||
|
||||
>[Go database/sql tutorial](http://go-database-sql.org/)ではよく使われる例と詳細な説明を提供しています。
|
||||
|
||||
## 目次
|
||||

|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ Next関数はひとつのデータを返すのに用いられます。データ
|
||||
|
||||
|
||||
## driver.RowsAffected
|
||||
RowsAffestedは実はint64のエイリアスです。しかしResultインターフェースを実装していますので、低レイヤーでResultの表示メソッドを実装するために用いられます。
|
||||
RowsAffectedは実はint64のエイリアスです。しかしResultインターフェースを実装していますので、低レイヤーでResultの表示メソッドを実装するために用いられます。
|
||||
|
||||
type RowsAffected int64
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ GoではMySQLをサポートしたドライバが現在比較的多く、以下
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "github.com/Go-SQL-Driver/MySQL"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"database/sql"
|
||||
"fmt"
|
||||
//"time"
|
||||
@@ -114,7 +114,7 @@ GoではMySQLをサポートしたドライバが現在比較的多く、以下
|
||||
|
||||
キーとなるいくつかの関数についてご説明します:
|
||||
|
||||
sql.Open()関数は登録済みのデータベースドライバを開くために使用されます。Go-MySQL-Driverの中でmysqlのデータベースドライバを登録し、2つ目の引数はDSN(Data Source Name)です。これはGo-MySQL-Driverが定義するデータベース接続と設定情報です。以下のシンタックスをサポートします:
|
||||
sql.Open()関数は登録済みのデータベースドライバを開くために使用されます。go-sql-driverの中でmysqlのデータベースドライバを登録し、2つ目の引数はDSN(Data Source Name)です。これはgo-sql-driverが定義するデータベース接続と設定情報です。以下のシンタックスをサポートします:
|
||||
|
||||
user@unix(/path/to/socket)/dbname?charset=utf8
|
||||
user:password@tcp(localhost:5555)/dbname?charset=utf8
|
||||
|
||||
@@ -9,7 +9,7 @@ MySQLはOracleに買収され、現在徐々にクローズされつつありま
|
||||
## ドライバ
|
||||
GoはPostgreSQLをサポートしたドライバも非常に多く実装されています。国外では多くの人が開発でこのデータベースを使用しているためです。
|
||||
|
||||
- https://github.com/bmizerany/pq database/sqlドライバをサポートしています。純粋にGoで書かれています。
|
||||
- https://github.com/lib/pq database/sqlドライバをサポートしています。純粋にGoで書かれています。
|
||||
- https://github.com/jbarham/gopgsqldriver database/sqlドライバをサポートしています。純粋にGoで書かれています。
|
||||
- https://github.com/lxn/go-pgsql database/sqlドライバをサポートしています。純粋にGoで書かれています。
|
||||
|
||||
@@ -43,7 +43,7 @@ package main
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
_ "github.com/bmizerany/pq"
|
||||
_ "https://github.com/lib/pq"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
@@ -84,7 +84,7 @@ beedbインターフェースはもう一種類の挿入の方法を提供して
|
||||
|
||||
複数のデータを挿入
|
||||
|
||||
addslice := make([]map[string]interface{})
|
||||
addslice := make([]map[string]interface{}, 0)
|
||||
add:=make(map[string]interface{})
|
||||
add2:=make(map[string]interface{})
|
||||
add["username"] = "astaxie"
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
|
||||
この一章の学習を通じて、いろいろなデータベースをどのように操作するか学んできました。Webの中でも重要なデータの保存に関する問題が解決したので、みなさんのdatabase/sqlの設計思想により一歩進んだ理解が深まることを願っています。
|
||||
|
||||
>[Go database/sql tutorial](http://go-database-sql.org/)ではよく使われる例と詳細な説明を提供しています。
|
||||
|
||||
## links
|
||||
* [目次](<preface.md>)
|
||||
* 前へ: [NOSQLデータベースの操作](<05.6.md>)
|
||||
|
||||
@@ -60,8 +60,8 @@ wは入力する必要のあるresponse、cookieはstructです。cookieオブ
|
||||
|
||||
例を一つ見てみましょう。どのようにcookieを設定するかです。
|
||||
|
||||
expiration := *time.LocalTime()
|
||||
expiration.Year += 1
|
||||
expiration := time.Now()
|
||||
expiration = expiration.AddDate(1, 0, 0)
|
||||
cookie := http.Cookie{Name: "username", Value: "astaxie", Expires: expiration}
|
||||
http.SetCookie(w, &cookie)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
- func RemoveAll(path string) error
|
||||
|
||||
pathに従って階層的なサブディレクトリを削除します。たとえばpathがひとつの名前であれば、このディレクトリは削除されません。
|
||||
pathに従って階層的なサブディレクトリを削除します。たとえばpathがあるひとつの名前であった場合、このディレクトリ以下のサブディレクトリが全て削除されます。
|
||||
|
||||
|
||||
以下はコード例です:
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
- func Trim(s string, cutset string) string
|
||||
|
||||
s文字列からcutsetで指定した文字列を除去する。
|
||||
s文字列の先頭と末尾からcutsetで指定した文字列を除去する。
|
||||
|
||||
fmt.Printf("[%q]", strings.Trim(" !!! Achtung !!! ", "! "))
|
||||
//Output:["Achtung"]
|
||||
|
||||
@@ -24,15 +24,15 @@
|
||||
ブログの主なルーティング規則は以下のようになります:
|
||||
|
||||
//ブログのトップページを表示
|
||||
beego.RegisterController("/", &controllers.IndexController{})
|
||||
beego.Router("/", &controllers.IndexController{})
|
||||
//ブログの詳細な情報を検索
|
||||
beego.RegisterController("/view/:id([0-9]+)", &controllers.ViewController{})
|
||||
beego.Router("/view/:id([0-9]+)", &controllers.ViewController{})
|
||||
//ブログの文章を作成
|
||||
beego.RegisterController("/new", &controllers.NewController{})
|
||||
beego.Router("/new", &controllers.NewController{})
|
||||
//ブログの削除
|
||||
beego.RegisterController("/delete/:id([0-9]+)", &controllers.DeleteController{})
|
||||
beego.Router("/delete/:id([0-9]+)", &controllers.DeleteController{})
|
||||
//ブログの編集
|
||||
beego.RegisterController("/edit/:id([0-9]+)", &controllers.EditController{})
|
||||
beego.Router("/edit/:id([0-9]+)", &controllers.EditController{})
|
||||
|
||||
|
||||
## データベーススキーマ
|
||||
@@ -66,8 +66,7 @@ ViewController:
|
||||
}
|
||||
|
||||
func (this *ViewController) Get() {
|
||||
inputs := this.Input()
|
||||
id, _ := strconv.Atoi(this.Ctx.Params[":id"])
|
||||
id, _ := strconv.Atoi(this.Ctx.Input.Params(":id"))
|
||||
this.Data["Post"] = models.GetBlog(id)
|
||||
this.Layout = "layout.tpl"
|
||||
this.TplNames = "view.tpl"
|
||||
@@ -101,8 +100,7 @@ EditController
|
||||
}
|
||||
|
||||
func (this *EditController) Get() {
|
||||
inputs := this.Input()
|
||||
id, _ := strconv.Atoi(this.Ctx.Params[":id"])
|
||||
id, _ := strconv.Atoi(this.Ctx.Input.Params[":id"])
|
||||
this.Data["Post"] = models.GetBlog(id)
|
||||
this.Layout = "layout.tpl"
|
||||
this.TplNames = "new.tpl"
|
||||
@@ -126,8 +124,10 @@ DeleteController
|
||||
}
|
||||
|
||||
func (this *DeleteController) Get() {
|
||||
id, _ := strconv.Atoi(this.Ctx.Params[":id"])
|
||||
this.Data["Post"] = models.DelBlog(id)
|
||||
id, _ := strconv.Atoi(this.Ctx.Input.Params(":id"))
|
||||
blog := GetBlog(id int)
|
||||
this.Data["Post"] = blog
|
||||
models.DelBlog(blog)
|
||||
this.Ctx.Redirect(302, "/")
|
||||
}
|
||||
|
||||
|
||||
2
ja/ebook/README.md
Normal file
2
ja/ebook/README.md
Normal file
@@ -0,0 +1,2 @@
|
||||
# Go Web プログラミング
|
||||
Webプログラミングが好きでGo webプログラミングを書きました。皆さんに気にいってもらえれば幸いです。
|
||||
96
ja/ebook/SUMMARY.md
Normal file
96
ja/ebook/SUMMARY.md
Normal file
@@ -0,0 +1,96 @@
|
||||
* [Goの環境設定](01.0.md)
|
||||
* [Goのインストール](01.1.md)
|
||||
* [GOPATHとワーキングディレクトリ](01.2.md)
|
||||
* [Goのコマンド](01.3.md)
|
||||
* [Goの開発ツール](01.4.md)
|
||||
* [まとめ](01.5.md)
|
||||
* [Go言語の基礎](02.0.md)
|
||||
* [こんにちは、Go](02.1.md)
|
||||
* [Goの基礎](02.2.md)
|
||||
* [フローと関数](02.3.md)
|
||||
* [struct型](02.4.md)
|
||||
* [オブジェクト指向](02.5.md)
|
||||
* [interface](02.6.md)
|
||||
* [マルチスレッド](02.7.md)
|
||||
* [まとめ](02.8.md)
|
||||
* [Webの基礎](03.0.md)
|
||||
* [webでの作業方法](03.1.md)
|
||||
* [Goで簡単なwebサーバを立てる](03.2.md)
|
||||
* [Goはどのようにしてweb作業を行うか](03.3.md)
|
||||
* [Goのhttpパッケージ詳細](03.4.md)
|
||||
* [まとめ](03.5.md)
|
||||
* [フォーム](04.0.md)
|
||||
* [フォームの入力を処理する](04.1.md)
|
||||
* [フォームに入力された内容の検証](04.2.md)
|
||||
* [クロスサイトスクリプティングの予防](04.3.md)
|
||||
* [フォームの複数回送信の防止](04.4.md)
|
||||
* [ファイルのアップロード処理](04.5.md)
|
||||
* [まとめ](04.6.md)
|
||||
* [データベースへのアクセス](05.0.md)
|
||||
* [database/sqlインターフェース](05.1.md)
|
||||
* [MySQL データベースの使用](05.2.md)
|
||||
* [SQLiteデータベースの使用](05.3.md)
|
||||
* [PostgreSQLデータベースの使用](05.4.md)
|
||||
* [beedbライブラリを使用してORM開発を行う](05.5.md)
|
||||
* [NOSQLデータベースの操作](05.6.md)
|
||||
* [まとめ](05.7.md)
|
||||
* [sessionとデータの保存](06.0.md)
|
||||
* [sessionとcookie](06.1.md)
|
||||
* [Goはどのようにしてsessionを使用するか](06.2.md)
|
||||
* [sessionストレージ](06.3.md)
|
||||
* [sessionハイジャックの予防](06.4.md)
|
||||
* [まとめ](06.5.md)
|
||||
* [テキスト処理](07.0.md)
|
||||
* [XMLの処理](07.1.md)
|
||||
* [JSONの処理](07.2.md)
|
||||
* [正規表現の処理](07.3.md)
|
||||
* [テンプレートの処理](07.4.md)
|
||||
* [ファイルの操作](07.5.md)
|
||||
* [文字列の処理](07.6.md)
|
||||
* [まとめ](07.7.md)
|
||||
* [Webサービス](08.0.md)
|
||||
* [Socketプログラミング](08.1.md)
|
||||
* [WebSocket](08.2.md)
|
||||
* [REST](08.3.md)
|
||||
* [RPC](08.4.md)
|
||||
* [まとめ](08.5.md)
|
||||
* [セキュリティと暗号化](09.0.md)
|
||||
* [CSRF攻撃の予防](09.1.md)
|
||||
* [入力フィルタリングの確保](09.2.md)
|
||||
* [XSS攻撃の回避](09.3.md)
|
||||
* [SQLインジェクションの回避](09.4.md)
|
||||
* [パスワードの保存](09.5.md)
|
||||
* [データを暗号化/復元する](09.6.md)
|
||||
* [まとめ](09.7.md)
|
||||
* [国際化とローカライズ](10.0.md)
|
||||
* [デフォルトロケールの設定](10.1.md)
|
||||
* [ローカライズリソース](10.2.md)
|
||||
* [国際化サイト](10.3.md)
|
||||
* [まとめ](10.4.md)
|
||||
* [エラー処理、デバッグとテスト](11.0.md)
|
||||
* [エラー処理](11.1.md)
|
||||
* [GDBを使用したデバッグ](11.2.md)
|
||||
* [Goによるテスト例](11.3.md)
|
||||
* [まとめ](11.4.md)
|
||||
* [デプロイとメンテナンス](12.0.md)
|
||||
* [アプリケーションログ](12.1.md)
|
||||
* [サイトのエラー処理](12.2.md)
|
||||
* [アプリケーションのデプロイ](12.3.md)
|
||||
* [バックアップとリストア](12.4.md)
|
||||
* [まとめ](12.5.md)
|
||||
* [どのようにしてWebフレームワークを設計するか](13.0.md)
|
||||
* [プロジェクトプラン](13.1.md)
|
||||
* [カスタムルータの設計](13.2.md)
|
||||
* [controllerの設計](13.3.md)
|
||||
* [ログとデプロイ設計](13.4.md)
|
||||
* [ブログの追加/削除/修正の実装](13.5.md)
|
||||
* [まとめ](13.6.md)
|
||||
* [Webフレームワークの拡張](14.0.md)
|
||||
* [静的ファイルのサポート](14.1.md)
|
||||
* [Sessionのサポート](14.2.md)
|
||||
* [フォームのサポート](14.3.md)
|
||||
* [ユーザ認証](14.4.md)
|
||||
* [多言語サポート](14.5.md)
|
||||
* [pprofのサポート](14.6.md)
|
||||
* [まとめ](14.7.md)
|
||||
* 付録A [参考資料](ref.md)
|
||||
Reference in New Issue
Block a user