Merging other languages

This commit is contained in:
James Miranda
2016-09-23 18:01:10 -03:00
parent 380a8ee74c
commit de3c5bdaa4
490 changed files with 24539 additions and 24588 deletions

View File

@@ -1,23 +1,23 @@
# 1 GOの環境設定
Goの世界へようこそ、さっそく初めてみましょう
Goは新しい言語です、並列処理、ガベージコレクションを備え、軽快にコンパイルできる言語です。以下のような特徴を持っています:
- 一台のコンピュータ上であっという間に大型のGoプログラムをコンパイルすることができます。
- Goはソフトウェアの構造にモデルを与えます。分析をより簡単にこなすことができ、ファイルライブラリのincludeといったCスタイルの書き出しにありがちな部分を大幅に省くことができます。
- Goは静的型付け言語です。型に階層の概念が無いのでユーザはその関係にをとられることなく、典型的なオブジェクト指向言語よりももっとライトに感じるくらいです。
- Goは完全ガベージコレクションタイプの言語です。また、基本的な並列処理とネットワークをサポートしています。
- Goはマルチプロセッサ対応のソフトウェアを作成できるようデザインされています。
Goはコンパイラ型言語の一種です。インタプリタ型言語の軽い身のこなしと動的型付け言語の開発効率、それに静的型付け言語の安全性を兼ね備えています。また、今風のネットワークとマルチプロセッサもサポートしています。これらを実現するには、表現力豊かで且つ軽いクラスシステム並列処理とガベージコレクション厳格な依存定義などを言語レベルで満たしていなければなりません。どれもライブラリやツールでは解決しきれないものです。Goその要望に応えます。
この章ではGoのインストール方法と設定についてご紹介します。
## 目次
![](images/navi1.png?raw=true)
## links
* [目次](<preface.md>)
* 次へ: [Goのインストール](<01.1.md>)
# 1 GOの環境設定
Goの世界へようこそ、さっそく初めてみましょう
Goは新しい言語です、並列処理、ガベージコレクションを備え、軽快にプログラムできる言語です。以下のような特徴を持っています:
- 一台のコンピュータ上であっという間に大型のGoプログラムを作り出すことができます。
- Goはソフトウェアの構造にモデルを提供します。分析をより簡単にこなせ、Cスタイルの頭にありがちなファイルライブラリのincludeの大部分を省くことができます。
- Goは静的型付け言語です。型に階層がありません。このためユーザは型の定義の関係に時間をとられることなく、典型的なオブジェクト指向言語よりももっとライトに感じるくらいです。
- Goは完全ガベージコレクションタイプの言語です。また、並列処理とネットワークを基本的にサポートしています。
- Goはマルチプロセッサ対応のソフトウェアを作成できるようデザインされています。
Goはコンパイラ型言語の一種です。インタプリタ型言語の軽い身のこなしと動的型付け言語の開発効率、それに静的型付け言語の安全性を兼ね備えています。また、モダンにネットワークとマルチプロセッサもサポートしています。これらの目標を達成するには、解決しなければならない言語上の問題がいくつかあります:表現力豊かだけれども軽いシステム並列処理とガベージコレクション厳格な依存定義などです。これらはライブラリやツール無しにはうまくいきません。Goその要望に応えます。
この章ではGoのインストール方法と設定について述べます。
## 目次
![](images/navi1.png?raw=true)
## links
* [目次](<preface.md>)
* 次へ: [Goのインストール](<01.1.md>)

View File

@@ -1,68 +1,64 @@
# 1.1 Goのインストール
## 3つのインストール方法
Goにはいくつものインストール方法があります。どれでも好きなのを選んでかまいません。ここでは3つのよくあるインストール方法をご紹介しま
Goにはいくつものインストール方法があります。どれでも好きなのを選んでかまいません。ここでは3つのよくあるインストール方法をご紹介しましょう
- ソースコードのインストール標準的なインストール方法です。Unix系システムをよく使うユーザ、特に開発者であれば、設定を好みに合わせて変更できます。
- 標準パッケージのインストールGoは便利なインストールパッケージを用意しています。Windows, Linux, Macなどのシステムをサポートしています。とりあえずさっとインストールするにはうってつけでしょう。システムのbit数に対応したインストールパッケージをダウンロードして、"Next"をたどるだけでインストールできます。 **おすすめ**
- ソースコードのインストール標準的なインストール方法です。Unix系システムをよく使うユーザ、特に開発者にとってはお馴染みの方法です。
- 標準パッケージのインストールGoは便利なインストールパッケージを用意しています。Windows, Linux, Macなどのシステムをサポートしています。初心者にはうってつけでしょう。システムのbit数に対応したインストールパッケージをダウンロードして、"Next"をたどるだけでインストールできます。
- サードパーティツールによるインストール現在便利なサードパーティパッケージも多くあります。たとえばUbuntuのapt-get、Macのhomebrewなどです。これらのシステムに慣れたユーザにはぴったりのインストール方法です。
最後に同じシステムの中で異なるバージョンのGoをインストールする場合は、[GVM](https://github.com/moovweb/gvm)が参考になります。どうすればよいか分からない場合一番うまくやれます。
最後に同じシステムの中で異なるバージョンのGoをインストールする場合は、[GVM](https://github.com/moovweb/gvm)が参考になります。どうすればよいか分からない場合一番うまくできます。
## Goソースコードのインストール
GoソースコードはPlan 9 CとAT&Tコンパイラを使って書かれている部分があります。もしソースコードからインストールしたい場合は、あらかじめCのコンパイルツールをインストールしておく必要があります。
Goソースコードの中で、いくつかの部分はPlan 9 CとAT&Tコンパイラを使っています。そのため、もしあなたがソースコードインストールしたい場合は、Cのコンパイルツールをインストールしておく必要があります。
Macでは、Xcodeに適切なコンパイラが含まれています。
Macシステムでは、Xcodeに適切なコンパイラが含まれています。
Unixでは、gccなどのツールをインストールする必要があります。例えばUbuntuではターミナルで`sudo apt-get install gcc libc6-dev`を実行することでコンパイラをインストールすることができます。
Unixシステムでは、gccなどのツールをインストールする必要があります。例えばUbuntuシステムではターミナルで`sudo apt-get install gcc libc6-dev`を実行することでコンパイラをインストールすることができます。
Windowsでは、MinGWをインストールする必要があります。その後MinGWでgccをインストールして、適切な環境変数を設定します。
Windowsシステムでは、MinGWをインストールする必要があります。その後MinGWでgccをインストールして、適切な環境変数を設定します。
直接オフィシャルサイトから[ソースコードをダウンロード](http://golang.org/dl/)できます。対応する`goVERSION.src.tar.gz`のファイルをダウンロードし、`$HOME`ディレクトリに解凍してから以下のコマンドを実行します
Goは[Mercurial][hg]を使ってバージョン管理を行います、まずMercurialをインストールしなければ、ダウンロードできません。もしMercurialがインストールされているのであれば、以下のコドを実行します
もしGoのインストールディレクトリが`$GO_INSTALL_DIR`だったとすると
hg clone -u release https://code.google.com/p/go
cd go/src
./all.bash
all.bashを実行後"ALL TESTS PASSED"が表示されると、インストール成功です。
上記はUnixスタイルのコマンドです、Windowsインストール方法は似ており、`all.bat`を実行するだけです。コンパイラはMinGWのgccを使います。
上記はUnixスタイルのコマンドです、Windowsではインストール方法は似ており、all.batを実行するだけです。コンパイラはMinGWのgccを使います。
もしMacまたはUnixユーザであればいくつかの環境変数を設定する必要があります。再起動しても有効にしたい場合は以下のコマンドを`.bashrc``.zsh`に書いておきます
その後環境変数をいくつか設定します
export GOPATH=$HOME/gopath
export PATH=$PATH:$HOME/go/bin:$GOPATH/bin
export GOROOT=$HOME/go
export GOBIN=$GOROOT/bin
export PATH=$PATH:$GOBIN
ファイルに書き込んだ場合は、`bash .bashrc``bash .zshrc`を実行してすぐに設定を有効にします。
Windowsシステムの場合は、環境変数を設定する必要があります。pathにgoが存在するディレクトリを追加し、gopath変数を設定します。
設定が終わり、コマンドプロンプトで`go`を入力すると、下図のような画面が表示されるはずです。
下のような画像が現れると、インストール成功です。
![](images/1.1.mac.png?raw=true)
図1.1 ソースコードインストール後Goコマンドを実行
図1.1 ソースコードインストール後Goコマンドを実行するの図
GoのUsage情報が表示されれば、Goインストール成功もしこのコマンドが存在しない場合は、PATH環境変数のなかにGoのインストールディレクトリが含まれているか確認してください。
もしGoのUsage情報が現れたら、Goインストール成功しています:もしこのコマンドが存在しない場合は、自分のPATH環境変数のなかにGoのインストールディレクトリが含まれているか確認してください。
> GOPATHについては以降の章で詳しくご説明します
## Go標準パッケージのインストール
Goはさまざまなプラットホームでインストールパッケージを提供しています、これらのパッケージはデフォルトで以下のディレクトリにインストールします/usr/local/goWindowsc:\Go。当然これらのインストール場所を変更することもできます、ただし変更後はあなたの環境変数を以下のように設定する必要があります
Goはさまざまなプラットホームでインストールパッケージを提供しています、これらのパッケージはデフォルトで以下のディレクトリにインストールします/usr/local/goWindowsシステムc:\Go。当然これらのインストール場所を変更することもできます、ただし変更後はあなたの環境変数を以下のように設定する必要があります
export GOROOT=$HOME/go
export GOPATH=$HOME/gopath
export PATH=$PATH:$GOROOT/bin:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
これらのコマンドはMacやUnixユーザであれば`.bashrc``.zshrc`ファイルに入れておくべきでしょう。Windowsユーザであれば当然環境変数に入れておきます
### 自分の操作しているシステムが32bitか64bitか判断する方法
### 自分の操作しているシステムが32bitか64bitか判断する方法
Goインストールの次はシステムのbit数の判断ですので、この章では先に自分のシステムの種類を確認しましょう。
Goのインストールにはオペレーティングシステムのbit数を判断する必要があるので、この章では先に自分のシステムの種類を確認しましょう
WindowsシステムのユーザはWin+Rを押してcmdを実行してください。`systeminfo`と入力してエンターキーを押します。少しするとシステムの情報が現れます。"システムの種類"の一行に、"x64-based PC"と表示されていれば、64bitシステムです。もし"X86-based PC"とあれば、32bitシステムです
WindowsのユーザはWin+Rを押してcmdを実行してください。`systeminfo`と入力してエンターキーを押します。しばらくするとシステムの情報が表示されます。"システムの種類"の一行に"x64-based PC"と表示されていれば64bitシステムです。もし"X86-based PC"とあれば、32bitシステムです。
Macユーザは直接64bit版を使用することをおすすめします。GoがサポートしているMac OS Xのバージョンは、すでに32bitプロセッサをサポートしていないためです。
Macユーザは直接64bit版を使用することをおすすめします。なぜなら、GoがサポートしているMac OS Xのバージョンはすでに32bitプロセッサをサポートしていないからです。
LinuxユーザはTerminalで`arch`(すなわち、`uname -a`)を実行することでシステムの情報を確かめることができます。
@@ -76,19 +72,19 @@ LinuxユーザはTerminalで`arch`(すなわち、`uname -a`)を実行するこ
### Mac インストール
[ダウンロードURL][downlink]にアクセスし、32bitシステムはgo1.4.2.darwin-386-osx10.8.pkgをダウンロードします。64bitシステムであればgo1.4.2.darwin-amd64-osx10.8.pkgをダウンロードします。ファイルをダブルクリックし、すべてデフォルトで「次へ」ボタンをクリックします。これでgoはあなたのシステムにインストールされました。デフォルトでPATHの中に適切な`~/go/bin`が追加されています。端末を開いて`go`と入力します。
[ダウンロードURL][downlink]に接続し、32bitシステムはgo1.0.3.darwin-386.pkgをダウンロードします。64bitシステムであればgo1.0.3.darwin-amd64.pkgをダウンロードします。ファイルをダブルクリックし、すべてデフォルトで「次へ」ボタンをクリックします。これでgoはあなたのシステムにインストールされました。デフォルトでPATHの中に適切な`~/go/bin`が追加されています。このとき端末を開き、`go`と入力します。
インストール成功の画像が表示されればインストール成功です。
インストール成功の画像があらわれるとインストール成功です。
もしgoのUsage情報が表示した場合は、goはすでにインストールされています。もしこのコマンドが存在しないと表示した場合は、自分のPATH環境変数の中にgoのインストールディレクトリが含まれているか確認してください。
もしgoのUsage情報が現れた場合は、goはすでにインストールされています。もしこのコマンドが存在しないと出てきた場合は、自分のPATH環境変数の中にgoのインストールディレクトリが含まれているか確認してください。
### Linux インストール
[ダウンロードURL][downlink]にアクセスし、32bitシステムであればgo1.4.2.linux-386.tar.gzを64bitシステムであればgo1.2.2.linux-amd64.tar.gzをダウンロードします。
[ダウンロードURL][downlink]に接続し、32bitシステムgo1.0.3.linux-386.tar.gzをダウンロードします。64bitシステムであればgo1.0.3.linux-amd64.tar.gzをダウンロードします。
以下ではGoがインストールされたディレクトリを`$GO_INSTALL_DIR`と仮定します。
今後はGoがインストールされたディレクトリを`$GO_INSTALL_DIR`と仮定します。
`tar.gz`をインストールディレクトリに解凍します:`tar zxvf go1.4.2.linux-amd64.tar.gz -C $GO_INSTALL_DIR`
`tar.gz`をインストールディレクトリに解凍します:`tar zxvf go1.0.3.linux-amd64.tar.gz -C $GO_INSTALL_DIR`
PATHを設定します。`export PATH=$PATH:$GO_INSTALL_DIR/go/bin`
@@ -96,36 +92,36 @@ PATHを設定します。`export PATH=$PATH:$GO_INSTALL_DIR/go/bin`
![](images/1.1.linux.png?raw=true)
図1.2 Linuxシステムでインストールに成功したあとgoを実行した時に表示する情報
図1.2 Linuxシステムでインストールに成功したあとgoを実行して表示される情報
もしgoのUsage情報が表示された場合は、goはすでにインストールされています。もしこのコマンドが存在しないと出てきた場合は、自分のPATH環境変数の中にgoのインストールディレクトリが含まれているか確認してください。
もしgoのUsage情報がれた場合は、goはすでにインストールされています。もしこのコマンドが存在しないと出てきた場合は、自分のPATH環境変数の中にgoのインストールディレクトリが含まれているか確認してください。
### Windows インストール ###
[Google Code ダウンロードページ][downlink]にアクセスし、32bit の場合は名前に windows-386 を含む msi パッケージを64bit であれば名前に windows-amd64 を含むものをダウンロードします。ダウンロード後実行しますが、デフォルトのインストールフォルダである C:\Go\を変更してはいけません。他の場所にインストールしてしまうと、あなたが書いた Go コードが実行できなくなってしまうかもしれません。インストールが終わるとデフォルトで環境変数 Path に Go のインストールフォルダの下にある bin フォルダ `C:\Go\bin\` が追加され、Go のインストールフォルダである `C:\Go\` の値が環境変数 GOROOT に追加されます。
[Google Code ダウンロードページ][downlink]に接続し、32bit の場合は名前に windows-386 を含む msi パッケージをダウンロードします。64bit であれば名前に windows-amd64 を含むものをダウンロードします。ダウンロード後実行しますが、デフォルトのインストールフォルダである C:\Go\を変更してはいけません。他の場所にインストールしてしまうと、あなたが書いた Go コードが実行できなくなってしまうかもしれません。インストールが終わるとデフォルトで環境変数 Path に Go のインストールフォルダの下にある bin フォルダ `C:\Go\bin\` が追加され、Go のインストールフォルダである `C:\Go\` の値が環境変数 GOROOT に追加されます。
** インストールが成功しているか確認する **
「ファイル名を指定して実行」に `cmd` を入力し、コマンドラインツールを開きます。プロンプトで`go`と入力することで Usage 情報が確認できるか確かめることができます。`cd %GOROOT%` を入力すると、Go のインストールフォルダに入れるか確認できます。どちらも成功していれば、インストールに成功しています。
「ファイル名を指定して実行」に `cmd` を入力することでコマンドラインツールを開きます。プロンプトで`go`と入力することで Usage 情報が確認できるか確かめることができます。`cd %GOROOT%` を入力すると、Go のインストールフォルダに入れるか確認できます。どちらも成功していれば、インストールに成功しています。
インストールに成功していなければ、環境変数 Path と GOROOT の値を確認してください。もし存在しなければアンインストールの上再インストールし、存在していればコンピュータを再起動し、上の手順を再度試しください。
インストールに成功していなければ、環境変数 Path と GOROOT の値を確認してください。もし存在しなければアンインストールの上再インストールし、存在していればコンピュータを再起動し、上の手順を再度試しください。
## サードパーティツールのインストール
### GVM
gvmはサードパーティが開発したGoのバージョン管理ツールです。rubyのrvmツールに似ています。相当使い勝手がいいです。gvmをインストールするには以下のコマンド実行します
bash < <(curl -s -S -L https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)
bash < <(curl -s https://raw.github.com/moovweb/gvm/master/binscripts/gvm-installer)
インストールが完了したあと、goをインストールすることができます
gvm install go1.4.2
gvm use go1.4.2
gvm install go1.1
gvm use go1.1
下のコマンドで、毎回gvm useをコールする手間を省くことができます
gvm use go1.4.2 --default
gvm use go1.1 --default
上のコマンドを実行したあと、GOPATH、GOROOTなどの環境変数自動的に設定されます。これで、直接利用することができます。
上のコマンドを実行したあと、GOPATH、GOROOTなどの環境変数自動的に設定されます。これで、直接利用することができます。
### apt-get
Ubuntuは現在最も多く利用されているLinuxデスクトップシステムです。`apt-get`コマンドでソフトウェア・パッケージを管理します。下のコマンドでGoをインストールすることができます、今後のため`git``mercurial`もインストールしておくべきでしょう:
@@ -136,7 +132,7 @@ Ubuntuは現在最も多く利用されているLinuxデスクトップシステ
sudo apt-get install golang-stable git-core mercurial
### homebrew
homebrewはMacで現在最も使用されているソフトウェア管理ツールです。現在Goをサポートしており、以下のコマンドでGoを直接インストールすることができます。今後のため`git``mercurial`もインストールしておくべきでしょう:
homebrewはMacシステムで現在最も使用されているソフトウェア管理ツールです。現在Goをサポートしており、以下のコマンドでGoを直接インストールすることができます。今後のため`git``mercurial`もインストールしておくべきでしょう:
brew update && brew upgrade
brew install go
@@ -149,4 +145,5 @@ homebrewはMacで現在最も使用されているソフトウェア管理ツー
* 前へ: [Goの環境設定](<01.0.md>)
* 次へ: [GOPATHとワーキングディレクトリ](<01.2.md>)
[downlink]:http://golang.org/dl/ "Goインストールパッケージダウンロード"
[downlink]: http://code.google.com/p/go/downloads/list "Goインストールパッケージダウンロード"
[hg]: http://mercurial.selenic.com/downloads/ "Mercurialダウンロード"

View File

@@ -1,204 +1,116 @@
# 1.3 Goのコマンド
## Goのコマンド
Go言語は完全なコマンド操作ツールセットを持つ言語です。コマンドラインで`go`を実行することでそれらを確認することができます:
![](images/1.1.mac.png?raw=true)
図1.3 Goコマンドで詳細情報を表示
これらのコマンドは我々が普段コードを書いている時に非常に役立つものです。次に普段使用するコマンドを理解していきましょう。
## go build
このコマンドは主にソースコードのコンパイルに用いられます。パッケージのコンパイル作業中、もし必要であれば、同時に関連パッケージもコンパイルすることができます。
- もし普通のパッケージであれば、我々が1.2章で書いた`mypath`パッケージのように、`go build`を実行したあと、何のファイルも生成しません。もし`$GOPATH/pkg`の下に対応するファイルを生成する必要があれば、`go install`を実行してください。
- もしそれが`main`パッケージであれば、`go build`を実行したあと、カレントディレクトリの下に実行可能ファイルが生成されます。もし`$GOPATH/bin`の下に対応するファイルを生成する必要があれば、`go install`を実行するか、`go build- o パス/a.exe`を実行してください。
- もしあるプロジェクトディレクトリに複数のファイルがある場合で、単一のファイルのみコンパイルしたい場合は、`go build`を実行する際にファイル名を追加することができます。例えば`go build a.go`です。`go build`コマンドはデフォルトでカレントディレクトリにある全てのgoファイルをコンパイルしようと試みます。
- コンパイル後に出力されるファイル名を指定することもできます。1.2章の`mathapp`アプリケーションでは`go build -o astaxie.exe`と指定できます。デフォルトはpackage名mainパッケージではないになるか、ソースファイルのファイル名mainパッケージになります。
実際はpackage名は[Go言語の規格](https://golang.org/ref/spec)においてコード中の"package"に続く名前になります。この名前はファイル名と異なっていても構いません。デフォルトで生成される実行可能ファイル名はディレクトリ名。
- go buildはディレクトリ内の"\_"または"."ではじまるgoファイルを無視します。
- もしあなたのソースコードが異なるオペレーティングシステムに対応する場合は異なる処理が必要となります。ですので異なるオペレーティングシステムの名称にもとづいてファイルを命名することができます。例えば配列を読み込むプログラムがあったとして、異なるオペレーティングシステムに対して以下のようなソースファイルがあるかもしれません。
array_linux.go
array_darwin.go
array_windows.go
array_freebsd.go
`go build`の際、システム名の末尾のファイルから選択的にコンパイルすることができますLinux、Darwin、Windows、Freebsd
引数の紹介
- `-o` 出力するファイル名を指定します。パスが含まれていても構いません。例えば `go build -o a/b/c`
- `-i` パッケージをインストールします。コンパイル+`go install`
- `-a` すでに最新であるパッケージを全て更新します。ただし標準パッケージには適用されません
- `-n` 実行が必要なコンパイルコマンドを出力します。ただし、実行はされません。これにより低レイヤーで一体何が実行されているのかを簡単に知る事ができます
- `-p n` マルチプロセスで実行可能なコンパイル数を指定します。デフォルトはCPU数です
- `-race` コンパイルを行う際にレースコンディションの自動検出を行います。64bitマシンでのみ対応しています
- `-v` 現在コンパイル中のパッケージ名を出力します
- `-work` コンパイル時の一時ディレクトリ名を出力し、すでに存在する場合は削除しなくなります
- `-x` 実行しているコマンドを出力します。`-n`の結果とよく似ていますが、この場合は実行します。
- `-ccflags 'arg list'` オプションを5c, 6c, 8cに渡してコールします
- `-compiler name` コンパイラを指定します。gccgoか、またはgcです
- `-gccgoflags 'arg list'` オプションをgccgoリンカに渡してコールします
- `-gcflags 'arg list'` オプションを5g, 6g, 8gに渡してコールします
- `-installsuffix suffix` デフォルトのインストールパッケージと区別するため、このサフィックスを利用して依存するパッケージをインストールします。`-race`をオプションに指定した場合はデフォルトで`-installsuffix race`が有効になっています。`-n`コマンドで確かめることができますよ
- `-ldflags 'flag list'` オプションを5l, 6l, 8lに渡してコールします。
- `-tags 'tag list'` コンパイル時にこれらのtagをつけることができます。tagの詳細な制限事項に関しては [Build Constraints](http://golang.org/pkg/go/build/) を参考にして下さい。
## go clean
このコマンドは現在のソースコードパッケージと関連するソースパッケージのなかでコンパイラが生成したファイルを取り除く操作を行います。これらのファイルはすなわち:
_obj/ 旧objectディレクトリ、MakeFilesが作成する。
_test/ 旧testディレクトリMakefilesが作成する。
_testmain.go 旧gotestファイルMakefilesが作成する。
test.out 旧testログMakefilesが作成する。
build.out 旧testログMakefilesが作成する。
*.[568ao] objectファイルMakefilesが作成する。
DIR(.exe) go buildが作成する。
DIR.test(.exe) go test -cが作成する。
MAINFILE(.exe) go build MAINFILE.goが作成する
*.so SWIG によって生成される。
私は基本的にこのコマンドを使ってコンパイルファイルを掃除します。ローカルでテストを行う場合これらのコンパイルファイルはシステムと関係があるだけで、コードの管理には必要ありません。
$ go clean -i -n
cd /Users/astaxie/develop/gopath/src/mathapp
rm -f mathapp mathapp.exe mathapp.test mathapp.test.exe app app.exe
rm -f /Users/astaxie/develop/gopath/bin/mathapp
引数紹介
- `-i` go installがインストールするファイル等の、関係するインストールパッケージと実行可能ファイルを取り除きます。
- `-n` 実行する必要のある削除コマンドを出力します。ただし実行はされません。これにより低レイヤで何が実行されているのかを簡単に知ることができます。
- `-r` importによってインポートされたパッケージを再帰的に削除します。
- `-x` 実行される詳細なコマンドを出力します。`-n`出力の実行版です
## go fmt
読者にC/C++の経験があればご存知かもしれませんが、コードにK&Rスタイルを選択するかANSIスタイルを選択するかは常に論争となっていました。goでは、コードに標準のスタイルがあります。すでに培われた習慣やその他が原因となって我々は常にANSIスタイルまたはその他のより自分にあったスタイルでコードを書いて来ました。これは他の人がコードを閲覧する際に不必要な負担を与えます。そのためgoはコードのスタイルを強制し例えば左大括弧はかならず行末に置く、このスタイルに従わなければコンパイルが通りません。整形の時間の節約するため、goツールは`go fmt`コマンドを提供しています。これはあなたの書いたコードを整形するのに役立ちます。あなたの書いたコードは標準のスタイルに修正されますが、我々は普段このコマンドを使いません。なぜなら開発ツールには一般的に保存時に自動的に整形を行ってくれるからです。この機能は実際には低レイヤでは`go fmt`を呼んでいます。この次の章で2つのツールをご紹介しましょう。この2つのツールはどれもファイルを保存する際に`go fmt`機能を自動化させます。
go fmtコマンドを使うにあたって実際にはgofmtがコールますが、-wオプションが必要になります。さもなければ、整形結果はファイルに書き込まれません。gofmt -w -l src、ですべての項目を整形することができます。
go fmtはgofmtの上位レイヤーのパッケージされたコマンドです。より個人的なフォーマットスタイルが欲しい場合は [gofmt](http://golang.org/cmd/gofmt/) を参考にしてください
gofmtの引数紹介
- `-l` フォーマットする必要のあるファイルを表示します。
- `-w` 修正された内容を標準出力に書き出すのではなく、直接そのままファイルに書き込みます。
- `-r` “a[b:len(a)] -> a[b:]”のような重複したルールを追加します。大量に変換を行う際に便利です。
- `-s` ファイルのソースコードを簡素化します。
- `-d` ファイルに書き込まず、フォーマット前後のdiffを表示します。デフォルトはfalseです。
- `-e` 全ての文法エラーを標準出力に書き出します。もしこのラベルを使わなかった場合は異なる10行のエラーまでしか表示しません。
- `-cpuprofile` テストモードをサポートします。対応するするcpufile指定のファイルに書き出します。
## go get
このコマンドは動的にリモートコードパッケージを取得するために用いられます。現在BitBucket、GitHub、Google CodeとLaunchpadをサポートしています。このコマンドは内部で実際には2ステップの操作に分かれます第1ステップはソースコードパッケージのダウンロード、第2ステップは`go install`の実行です。ソースコードパッケージのダウンロードを行うgoツールは異なるドメインにしたがって自動的に異なるコードツールを用います。対応関係は以下の通りです
BitBucket (Mercurial Git)
GitHub (Git)
Google Code Project Hosting (Git, Mercurial, Subversion)
Launchpad (Bazaar)
そのため、`go get`を正常に動作させるためには、あらかじめ適切なソースコード管理ツールがインストールされていると同時にこれらのコマンドがあなたのPATHに入っていなければなりません。実は`go get`はカスタムドメインの機能をサポートしています。具体的な内容は`go help remote`を参照ください。
引数紹介:
- `-d` ダウンロードするだけでインストールしません。
- `-f` `-u`オプションを与えた時だけ有効になります。`-u`オプションはimportの中の各パッケージが既に取得されているかを検証しなくなります。ローカルにforkしたパッケージに対して特に便利です。
- `-fix` ソースコードをダウンロードするとまずfixを実行してから他の事を行うようになります。
- `-t` テストを実行する為に必要となるパッケージも同時にダウンロードします。
- `-u` パッケージとその依存パッケージをネットワークから強制的に更新します。
- `-v` 実行しているコマンドを表示します。
## go install
このコマンドは実際には内部で2ステップの操作に分かれます。第1ステップはリザルトファイルの生成実行可能ファイルまたはaパッケージ、第2ステップはコンパイルし終わった結果を`$GOPATH/pkg`または`$GOPATH/bin`に移動する操作です。
引数は`go build`のコンパイルオプションをサポートしています。みなさんは`-v`オプションだけ覚えていただければ結構です。これにより低レイヤーの実行状況をいつでも確認することができます。
## go test
このコマンドを実行すると、ソースコードディレクトリ以下の`*_test.go`ファイルが自動的にロードされ、テスト用の実行可能ファイルが生成/実行されます。出力される情報は以下のようなものになります
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
デフォルトの状態で、オプションを追加する必要はありません。自動的にあなたのソースコードパッケージ以下のすべてのtestファイルがテストされます。もちろんオプションを追加しても構いません。詳細は`go help testflag`を確認してください。
ここでは良く使われるオプションについてご紹介します:
- `-bench regexp` 指定したbenchmarksを実行します。例えば `-bench=.`
- `-cover` テストカバー率を起動します。
- `-run regexp` regexpにマッチする関数だけを実行します。例えば `-run=Array` とすることで名前がArrayから始まる関数だけを実行します。
- `-v` テストの詳細なコマンドを表示します。
## go tool
`go tool`にはいくつものコマンドがあります。ここではつだけご紹介します。fixと vetです。
- `go tool fix .` は以前の古いバージョンを新しいバージョンに修復します。例えば、go1以前の古いバージョンのコードをgo1に焼き直したり、APIを変化させるといったことです。
- `go tool vet directory|files` はカレントディレクトリのコードが正しいコードであるか分析するために使用されます。例えばfmt.Printfをコールする際のオプションが正しくなかったり、関数の途中でreturnされたことによって到達不可能なコードが残っていないかといった事です。
## go generate
このコマンドはGo1.4になって初めてデザインされました。コンパイル前にある種のコードを自動で生成する目的に使用されます。`go generate``go build`は全くことなるコマンドです。ソースコード中の特殊なコメントをを分析することで、対応するコマンドを実行します。これらのコマンドは明確に何の依存も存在しません。この機能を使用する場合には必ず次の事を念頭に置いてください。`go generate`はあなたの為に存在します。あなたのパッケージを使用する誰かの為のものではありません。これはある一定のコードを生成するためにあります。
簡単な例をご紹介します。例えば我々が度々`yacc`を使ってコードを生成していたとしましょう。その場合以下のようなコマンドをいつも使用することになります:
go tool yacc -o gopher.go -p parser gopher.y
-o は出力するファイル名を指定します。-pはパッケージ名を指定します。これは単独のコマンドであり、もし`go generate`によってこのコマンドを実行する場合は当然ディレクトリの任意の`xxx.go`ファイルの任意の位置に以下のコメントを一行追加します。
//go:generate go tool yacc -o gopher.go -p parser gopher.y
注意すべきは、`//go:generate`に空白が含まれていない点です。これは固定のフォーマットで、ソースファイルを舐める時はこのフォーマットに従って判断されます。
これにより以下のようなコマンドによって、生成・コンパイル・テストを行うことができます。もし`gopher.y`ファイルに修正が発生した場合は、再度`go generate`を実行することでファイルを上書きすればよいことになります。
$ go generate
$ go build
$ go test
## godoc
Go1.2バージョンより以前は`go doc`コマンドがサポートされていましたが、今後は全てgodocコマンドに移されました。このようにインストールします`go get golang.org/x/tools/cmd/godoc`
多くの人がgoにはサードパーティのドキュメントが必要無いと謳っています。なぜなら例えばchmハンドブックのようにもっとも私はすでに[chmマニュアル](https://github.com/astaxie/godoc)を作っていますが)、この中にはとても強力なドキュメントツールが含まれているからです。
どのように対応するpackageのドキュメントを確認すればよいでしょうか
例えばbuiltinパッケージであれば、`go doc builtin`と実行します。
もしhttpパッケージであれば、`go doc net/http`と実行してください。
パッケージの中の関数を確認する場合は`godoc fmt Printf`としてください。
対応するコードを確認する場合は、`godoc -src fmt Printf`とします。
コマンドラインでコマンドを実行します。 godoc -http=:ポート番号 例えば`godoc -http=:8080`として、ブラウザで`127.0.0.1:8080`を開くと、golang.orgのローカルのcopy版を見ることができます。これを通してpkgドキュメントなどの他の内容を確認することができます。もしあなたがGOPATHを設定されていれば、pkgカテゴリの中で、標準パッケージのドキュメントのみならず、ローカルの`GOPATH`のすべての項目に関連するドキュメントをリストアップすることができます。これはグレートファイアーウォールの中にいるユーザにとっては非常にありがたい選択です。
## その他のコマンド
goは他にも様々なツールを提供しています。例えば以下のツール
go version はgoの現在のバージョンを確認します。
go env は現在のgoの環境変数を確認します。
go list は現在インストールされている全てのpackageをリストアップします。
go run はGoプログラムのコンパイルと実行を行います。
これらのツールはまだ多くのオプションがあり、ひとつひとつはご紹介しませんが、ユーザは`go help コマンド`で更に詳しいヘルプ情報を取得することができます。
## links
* [目次](<preface.md>)
* 前へ: [GOPATHとワーキングディレクトリ](<01.2.md>)
* 次へ: [Goの開発ツール](<01.4.md>)
# 1.3 Goのコマンド
## Goのコマンド
Go言語は完全なコマンド操作ツールセットを持つ言語です。コマンドラインで`go`を実行することでそれらを確認することができます:
![](images/1.3.go.png?raw=true)
図1.3 Goコマンドで詳細情報を表示
これらのコマンドは我々が普段コードを書いている時に非常に役立つものです。次に普段使用するコマンドを理解していきましょう。
## go build
このコマンドは主にコンパイルテストに用いられます。パッケージのコンパイル作業中、もし必要であれば、同時に関連パッケージもコンパイルすることができます。
- もし普通のパッケージであれば、我々が1.2章で書いた`mypath`パッケージのように、`go build`を実行したあと、何のファイルも生成しません。もし`$GOPATH/pkg`の下に対応するファイルを生成する必要があれば、`go install`を実行してください。
- もしそれが`main`パッケージであれば、`go build`を実行したあと、カレントディレクトリの下に実行可能ファイルが生成されます。もし`$GOPATH/bin`の下に対応するファイルを生成する必要があれば、`go install`を実行するか、`go build- o パス/a.exe`を実行してください。
- もしあるプロジェクトディレクトリに複数のファイルがある場合で、単一のファイルのみコンパイルしたい場合は、`go build`を実行する際にファイル名を追加することができます。例えば`go build a.go`です。`go build`コマンドはデフォルトでカレントディレクトリにある全てのgoファイルをコンパイルしようと試みます。
- コンパイル後に出力されるファイル名を指定することもできます。1.2章の`mathapp`アプリケーションでは`go build -o astaxie.exe`と指定できます。デフォルトはpackage名mainパッケージではないになるか、ソースファイルのファイル名mainパッケージになります。
実際はpackage名は[Go言語の規格](https://golang.org/ref/spec)においてコード中の"package"に続く名前になります。この名前はファイル名と異なっていても構いません。デフォルトで生成される実行可能ファイル名はディレクトリ名。
- go buildはディレクトリ内の"\_"または"."ではじまるgoファイルを無視します。
- もしあなたのソースコードが異なるオペレーティングシステムに対応する場合は異なる処理が必要となります。ですので異なるオペレーティングシステムの名称にもとづいてファイルを命名することができます。例えば配列を読み込むプログラムがあったとして、異なるオペレーティングシステムに対して以下のようなソースファイルがあるかもしれません。
array_linux.go
array_darwin.go
array_windows.go
array_freebsd.go
`go build`の際、システム名の末尾のファイルから選択的にコンパイルすることができますLinux、Darwin、Windows、Freebsd
## go clean
このコマンドは現在のソースコードパッケージのなかでコンパイラが生成したファイルを取り除く操作を行います。これらのファイルはすなわち:
_obj/ 旧objectディレクトリ、MakeFilesが作成する
_test/ 旧testディレクトリMakefilesが作成する
_testmain.go 旧gotestファイルMakefilesが作成する
test.out 旧testログMakefilesが作成する
build.out 旧testログMakefilesが作成する
*.[568ao] objectファイルMakefilesが作成する
DIR(.exe) go buildが作成する
DIR.test(.exe) go test -cが作成する
MAINFILE(.exe) go build MAINFILE.goが作成する
私は基本的にこのコマンドを使ってコンパイルファイルを掃除します。ローカルでテストを行う場合これらのコンパイルファイルはシステムと関係があるだけで、コードの管理には必要ありません
## go fmt
読者にC/C++の経験があればご存知かもしれませんが、コードにK&Rスタイルを選択するかANSIスタイルを選択するかは常に論争となっていました。goでは、コードに標準のスタイルがあります。すでに培われた習慣やその他が原因となって我々は常にANSIスタイルまたはその他のより自分にあったスタイルでコードを書いて来ました。これは他の人がコードを閲覧する際に不必要な負担を与えます。そのためgoはコードのスタイルを強制し例えば左大括弧はかならず行末に置く、このスタイルに従わなければコンパイルが通りません。整形の時間の節約するため、goツールは`go fmt`コマンドを提供しています。これはあなたの書いたコードを整形するのに役立ちます。あなたの書いたコードは標準のスタイルに修正されますが、我々は普段このコマンドを使いません。なぜなら開発ツールには一般的に保存時に自動的に整形を行ってくれるからです。この機能は実際には低レイヤでは`go fmt`を呼んでいます。この次の章で2つのツールをご紹介しましょう。この2つのツールはどれもファイルを保存する際に`go fmt`機能を自動化させます。
>go fmtコマンドの使用では、多くの場合はgofmtを使用しますが、-wオプションが必要になります。さもなければ、整形結果はファイルに書き込まれません。gofmt -w src、ですべての項目を整形することができます。
## go get
このコマンドは動的にリモートコードパッケージを取得するために用いられます。現在BitBucket、GitHub、Google CodeとLaunchpadをサポートしています。このコマンドは内部で実際には2ステップの操作に分かれます第1ステップはソースコードパッケージのダウンロード、第2ステップは`go install`の実行です。ソースコードパッケージのダウンロードを行うgoツールは異なるドメインにしたがって自動的に異なるコードツールを用います。対応関係は以下の通りです
BitBucket (Mercurial Git)
GitHub (Git)
Google Code Project Hosting (Git, Mercurial, Subversion)
Launchpad (Bazaar)
そのため、`go get`を正常に動作させるためには、あらかじめ適切なソースコード管理ツールがインストールされていると同時にこれらのコマンドがあなたのPATHに入っていなければなりません。実は`go get`はカスタムドメインの機能をサポートしています。具体的な内容は`go help remote`を参照ください
## go install
このコマンドは実際には内部で2ステップの操作に分かれます。第1ステップはリザルトファイルの生成実行可能ファイルまたはaパッケージ、第2ステップはコンパイルし終わった結果を`$GOPATH/pkg`または`$GOPATH/bin`に移動する操作です。
## go test
このコマンドを実行すると、ソースコードディレクトリ以下の`*_test.go`ファイルが自動的にロードされ、テスト用の実行可能ファイルが生成/実行されます。出力される情報は以下のようなものになります
ok archive/tar 0.011s
FAIL archive/zip 0.022s
ok compress/gzip 0.033s
...
デフォルトの状態で、オプションを追加する必要はありません。自動的にあなたのソースコードパッケージ以下のすべてのtestファイルがテストされます。もちろんオプションを追加しても構いません。詳細は`go help testflag`を確認してください
## go doc
(1.2rc1 から go doc コマンドはなくなり、 godoc コマンドのみになります)
多くの人がgoはいかなるサードパーティドキュメントも必要としないと言っています。なぜなら例えばchmマニュアルのようにもっとも私はすでに[chmマニュアル](https://github.com/astaxie/godoc)を作っていますが)、この中にすでに非常に協力なドキュメントツールが入っているからです。
どのように対応するpackageのドキュメントを確認すればよいでしょうか
例えばbuiltinパッケージであれば、`go doc builtin`と実行します
もしhttpパッケージであれば、`go doc net/http`と実行してください。
パッケージの中の関数を確認する場合は`godoc fmt Printf`としてください。
対応するコードを確認する場合は、`godoc -src fmt Printf`とします。
コマンドラインでコマンドを実行します。 godoc -http=:ポート番号 例えば`godoc -http=:8080`として、ブラウザで`127.0.0.1:8080`を開くと、golang.orgのローカルのcopy版を見ることができます。これを通してpkgドキュメントなどの他の内容を確認することができます。もしあなたがGOPATHを設定されていれば、pkgカテゴリの中で、標準パッケージのドキュメントのみならず、ローカルの`GOPATH`のすべての項目に関連するドキュメントをリストアップすることができます。これはグレートファイアーウォールの中にいるユーザにとっては非常にありがたい選択です。
## その他のコマンド
goは他にも様々なツールを提供しています。例えば以下のツール
go fix は以前の古いバージョンのコードを新しいバージョンに復元するために使われます。例えばgo1の前の古いバージョンのコードをgo1に移動させます。
go version はgoの現在のバージョンを確認します。
go env は現在のgoの環境変数を確認します。
go list は現在インストールされている全てのpackageをリストアップします。
go run はGoプログラムのコンパイルと実行を行います。
以上これらのツールはまだ多くのオプションがあり、ひとつひとつはご紹介しませんが、ユーザは`go help コマンド`で更に詳しいヘルプ情報を取得することができます。
## links
* [目次](<preface.md>)
* 前へ: [GOPATHとワーキングディレクトリ](<01.2.md>)
* 次へ: [Goの開発ツール](<01.4.md>)

View File

@@ -1,25 +1,25 @@
# 4 フォーム
フォームは普段Webアプリケーションを書く時によく使われるツールです。フォームを通して便利にユーザにサーバとデータをやり取りさせることができます。以前にWeb開発をしたことのあるユーザにとってはフォームはとてもお馴染みのものです。しかしC/C++のプログラマからすると少々取っ付きにくいかもしれません。フォームとは一体何でしょうか?
フォームは表の要素を含むエリアです。フォームの要素はユーザがフォームの中で(例えば、テキストフィールド、コンボボックス、チェックボックス、セレクトボックス等です。)情報を入力する要素です。フォームはフォームタグ(\<form\>)で定義します。
<form>
...
input 要素
...
</form>
Goではformの処理に簡単な方法が既に用意されています。Requestの中にformを専門に処理するものがあり簡単にWeb開発に利用できす。4.1節の中でGoがどのようにフォームの入力を処理するかご説明します。いかなるユーザの入力も信用はできないので、これらの入力に対し検証を行う必要があります。4.2節では一般的にどのように検証を行うか、細かいデモンストレーションを行います。
HTTPプロトコルはステートレスなプロトコルです。ではどのようにして一人のユーザを同定するのでしょうかまた、フォームが複数回送信されてしまわないように保証するにはどうするのでしょうか4.3と4.4節ではcookie(cookieはクライアントに保存される情報です。HTTP Headerを通してサーバーとやり取りされます)等をより詳しくご紹介します。
フォームにはもうひとつファイルをアップロードできるという大きな機能があります。Goはファイルのアップロードをどのように処理しているのでしょうか大きなファイルをアップロードする際効率よく処理するにはどうすればよいでしょうか4.5節ではGoによるファイルのアップロード処理の知識を一緒に勉強します。
## 目次
![](images/navi4.png?raw=true)
## links
* [目次](<preface.md>)
* 前へ: [第三章まとめ](<03.5.md>)
* 次へ: [フォームの入力を処理する](<04.1.md>)
# 4 フォーム
フォームは我々が普段Webアプリケーションを書く時によく使ツールです。フォームを通して便利にユーザにサーバとデータをやり取りさせることができます。以前にWeb開発をしたことのあるユーザにとってはフォームはとてもお馴染みのものです。しかしC/C++のプログラマからすると少々ばかり門外漢かもしれません。フォームとは一体何でしょうか?
フォームは表の要素を含むエリアです。フォームの要素はユーザがフォームの中で(例えば、テキストフィールド、コンボボックス、チェックボックス、セレクトボックス等です。)情報を入力する要素です。フォームはフォームタグ(\<form\>)で定義します。
<form>
...
input 要素
...
</form>
Goではformの処理にすでにとても簡単な方法が用意されています。Requestの中にformを専門に処理するものがあります。とても簡単にWeb開発に利用できるものです。4.1節の中でGoがどのようにフォームの入力を処理するかご説明します。いかなるユーザの入力も信用はできないので、これらの入力に対しバリデーションを行う必要があります。4.2節ではどのように普通のバリデーションを行うか、細かいデモンストレーションを行います。
HTTPプロトコルはステートレスなプロトコルです。ではどのようにして一人のユーザを同定するのでしょうかまた、フォームが複数回送信されてしまわないように保証するにはどうするのでしょうか4.3と4.4節ではcookie(cookieはクライアントに保存される情報です。handlerとサーバを通る度にやり取りされるデータです。)等をより詳しくご紹介します。
フォームにはもうひとつファイルをアップロードできるという大きな機能があります。Goはファイルのアップロードをどのように処理しているのでしょうか大きなファイルをアップロードする際効率よく処理するにはどうすればよいでしょうか4.5節ではGoによるファイルのアップロード処理の知識を一緒に勉強します。
## 目次
![](images/navi4.png?raw=true)
## links
* [目次](<preface.md>)
* 前へ: [第三章まとめ](<03.5.md>)
* 次へ: [フォームの入力を処理する](<04.1.md>)

View File

@@ -1,58 +1,58 @@
# 4.4 フォームの複数回送信の防止
これまでにどこかのBBSやブログでご覧になったことがあるかもしれませんが、一つのスレッドや文章の後でいくつもの重複が記録されていることがあります。これらの大多数はユーザが複数回書き込みフォームを送信してしまったことによるものです。様々な原因でユーザはよくフォームを複数回送信してしまいます。通常はマウスの誤操作によるもので、送信ボタンをダブルクリックしてしまったり、一旦送信した内容を再度修正しようとして、ブラウザの戻るボタンを押した後に次へボタンではなくまた送信ボタンを押してしまうことによるものです。当然、故意によるものもあります。- - 例えばネット上のアンケート調査やくじ引きにおいて重複して投票するなどです。では、どのようにしてユーザが同じ内容のフォームの送信を行うことを効果的に防げるのでしょうか?
解決方法はフォームの中にユニークな値を持ったhiddenフィールドを追加することです。フォームを検証する際、このユニークな値を持ったフォームがすでに送信されているかどうか検証します。もしすでに送信されていれば、二回目の送信を拒絶します。そうでなければフォームに対して処理ロジックを行います。また、もしAjax形式で送信するフォームだった場合、フォームが送信された後javascriptによってフォームの送信ボタンを禁止します。
4.2節の例を改良してみましょう:
<input type="checkbox" name="interest" value="football">サッカー
<input type="checkbox" name="interest" value="basketball">バスケットボール
<input type="checkbox" name="interest" value="tennis">テニス
ユーザ名:<input type="text" name="username">
パスワード:<input type="password" name="password">
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="ログイン">
テンプレートの中に`token`というhiddenフィールドを追加しました。この値にはMD5(タイムスタンプ)によってユニークな値を割り当てます。この値をサーバに保存することでsessionによコントロールは6章でどのように保存するか解説します)フォームが送信される際の判定に使うことができます。
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //リクエストを受け取る方法
if r.Method == "GET" {
crutime := time.Now().Unix()
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, token)
} else {
//リクエストはログインデータです。ログインのロジックを実行して判断します。
r.ParseForm()
token := r.Form.Get("token")
if token != "" {
//tokenの合法性を検証します。
} else {
//tokenが存在しなければエラーを出します。
}
fmt.Println("username length:", len(r.Form["username"][0]))
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) //サーバ側に出力します。
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) //クライアントに出力します。
}
}
出力されるページのソースは以下の通り:
![](images/4.4.token.png?raw=true)
図4.4 tokenを追加した後クライアントが出力するソース情報
tokenはすでに出力値を持っていますので連続してページを更新することができます。この値が次々と変化するのがお分かりいただけるかと思います。このように毎回formが表示される時にユニークになるよう保証します。ユーザが送信するフォームは唯一性が保持されます。
この解決方法は悪意の無い攻撃に対しても防止することができます。また悪意のあるユーザに対してもしばらく効果があります。その後、ユーザーにこの悪意のある動機を捨てさせることができなかった場合は更に複雑な作業が必要となります。
## links
* [目次](<preface.md>)
* 前へ: [クロスサイトスクリプティングの予防](<04.3.md>)
* 次へ: [ファイルのアップロード処理](<04.5.md>)
# 4.4 フォームの複数回送信の防止
以前どこかのBBSやブログでご覧になったかもしれませんが、一つのスレや文章の後でいくつもの重複が記録されていることがあります。これらの大多数はユーザが複数回書き込みフォームを送信してしまったことによるものです。様々な原因でユーザはよくフォームを複数回送信してしまいます。通常はマウスの誤操作によるもので、送信ボタンをダブルクリックしてしまったり、一旦送信した内容を再度修正しようとして、ブラウザの戻るボタンを押した後に次へボタンではなくまた送信ボタンを押してしまうことによるものです。当然、故意によるものもあります。- - 例えばネット上のアンケート調査やくじ引きにおいて重複して投票するなどです。では、どのようにしてユーザが同じ内容のフォームの送信を行うことを効果的に防げるのでしょうか?
解決方法はフォームの中に唯一の値を持ったhiddenフィールドを追加することです。フォームを検証する際、この唯一の値を持ったフォームがすでに送信されているかどうか検証します。もしすでに送信されていれば、二回目の送信を拒絶します。そうでなければフォームに対して処理ロジックを行います。また、もしAjax形式で送信するフォームだった場合、フォームが送信された後javascriptによってフォームの送信ボタンを禁止します。
4.2節の例を改良してみましょう:
<input type="checkbox" name="interest" value="football">サッカー
<input type="checkbox" name="interest" value="basketball">バスケットボール
<input type="checkbox" name="interest" value="tennis">テニス
ユーザ名:<input type="text" name="username">
パスワード:<input type="password" name="password">
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="ログイン">
テンプレートの中に`token`というhiddenフィールドを追加しました。この値にはMD5(タイムスタンプ)によってユニークな値を割り当てます。この値をサーバに保存することでsessionによってコントロールは6章でどのように保存するか解説します)フォームが送信される際の判定に使うことができます。
func login(w http.ResponseWriter, r *http.Request) {
fmt.Println("method:", r.Method) //リクエストを受け取る方法
if r.Method == "GET" {
crutime := time.Now().Unix()
h := md5.New()
io.WriteString(h, strconv.FormatInt(crutime, 10))
token := fmt.Sprintf("%x", h.Sum(nil))
t, _ := template.ParseFiles("login.gtpl")
t.Execute(w, token)
} else {
//リクエストはログインデータです。ログインのロジックを実行して判断します。
r.ParseForm()
token := r.Form.Get("token")
if token != "" {
//tokenの合法性を検証します。
} else {
//tokenが存在しなければエラーを出します。
}
fmt.Println("username length:", len(r.Form["username"][0]))
fmt.Println("username:", template.HTMLEscapeString(r.Form.Get("username"))) //サーバ側に出力します。
fmt.Println("password:", template.HTMLEscapeString(r.Form.Get("password")))
template.HTMLEscape(w, []byte(r.Form.Get("username"))) //クライアントに出力します。
}
}
出力されるページのソースは以下の通り:
![](images/4.4.token.png?raw=true)
図4.4 tokenを追加した後クライアントが出力するソース情報
tokenはすでに出力値を持っていますので連続してページを更新することができます。この値が次々と変化するのがお分かりいただけるかと思います。このように毎回formが表示される時にユニークになるよう保証します。ユーザが送信するフォームは唯一性が保持されます。
この解決方法は悪意の無い攻撃に対しても防止することができます。また悪意のあるユーザに対してもしばらく効果があります。その後、この悪意のある動機を捨てることができなかった場合は更に複雑な作業が必要となります。
## links
* [目次](<preface.md>)
* 前へ: [クロスサイトスクリプティングの予防](<04.3.md>)
* 次へ: [ファイルのアップロード処理](<04.5.md>)

View File

@@ -1,85 +1,122 @@
# 9.6 データを暗号化/復号する
前の節では安全なパスワード保存の仕方を説明してきました。しかしあるときには、既にデータベースに保存されている、プライバシーに関わる暗号化されたデータを修正する必要があるかもしれません。データを復号することが必要な時は、既に述べた1方向ハッシュ関数の代わりに、対称鍵暗号アルゴリズムを使うべきです
## 高度な暗号化/復号
Go言語の`crypto`では対称鍵暗号アルゴリズムをサポートしています。二種類の高度暗号化モジュールがあります。
- `crypto/aes`パッケージ:AES(Advanced Encryption Standard)は、Rijndael暗号化アルゴリズムとも呼ばれます。アメリカの連邦政府が採用しているブロック暗号の標準です。
- `crypto/des`パッケージDES(Data Encryption Standard)は対称鍵暗号の標準です。これは現在最も広く使用されている鍵システムです。特に金融データのセキュリティの保護で使われています。かつてアメリカ連邦政府の暗号化のスタンダードでしたがすでにAESにとってかわられています。
これらつのアルゴリズムは使用方法が似ていますので、以下ではaesパッケージを使ってどのようにこれらのパッケージを使うのかを説明していきたいと思います。
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"os"
)
var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
func main() {
// 暗号化したい文字列
plaintext := []byte("My name is Astaxie")
// 暗号化された文字列を渡すと、plaintは渡された文字列になります。
if len(os.Args) > 1 {
plaintext = []byte(os.Args[1])
}
// aesの暗号化文字列
key_text := "astaxie12798akljzmknm.ahkjkljl;k"
if len(os.Args) > 2 {
key_text = os.Args[2]
}
fmt.Println(len(key_text))
// 暗号化アルゴリズムaesを作成
c, err := aes.NewCipher([]byte(key_text))
if err != nil {
fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key_text), err)
os.Exit(-1)
}
// 暗号化文字列
cfb := cipher.NewCFBEncrypter(c, commonIV)
ciphertext := make([]byte, len(plaintext))
cfb.XORKeyStream(ciphertext, plaintext)
fmt.Printf("%s=>%x\n", plaintext, ciphertext)
// 復号文字列
cfbdec := cipher.NewCFBDecrypter(c, commonIV)
plaintextCopy := make([]byte, len(plaintext))
cfbdec.XORKeyStream(plaintextCopy, ciphertext)
fmt.Printf("%x=>%s\n", ciphertext, plaintextCopy)
}
上では`aes.NewCipher`(引数keyはかならず16、24または32桁の[]byteとなります。それぞれAES-128, AES-192とAES-256アルゴリズムに対応します。)関数をコールすると`cipher.Block`インターフェースを返します。このインターフェースは3つの機能を実現します:
type Block interface {
// BlockSize returns the cipher's block size.
BlockSize() int
// Encrypt encrypts the first block in src into dst.
// Dst and src may point at the same memory.
Encrypt(dst, src []byte)
// Decrypt decrypts the first block in src into dst.
// Dst and src may point at the same memory.
Decrypt(dst, src []byte)
}
この3つの関数は暗号化/復号操作を実装します。詳細な操作はGoのドキュメントをご覧ください。
## まとめ
この節ではいくつかの暗号化アルゴリズムを紹介しました。これらのアルゴリズムは、Webアプリケーションにおける暗号化/復号の必要に応じて異なる方法で使用することができます。基本的な安全性のみを必要とするアプリケーションではAESアルゴリズムを使うことが勧められます。
## links
* [目次](<preface.md>)
* 前へ: [パスワードの保存](<09.5.md>)
* 次へ: [まとめ](<09.7.md>)
# 9.6 データを暗号化/復号する
前の節でどのようにしてパスワード保存するかご紹介しました。しかしあるときには、慎重に扱うべきデータを暗号化して保存し、将来のあるときにいつでもそれらを復元したい場合があります。この時双方向暗号アルゴリズムを使って我々の要求を満たさなければなりません
## base64で暗号化/復号する
もしWebアプリケーションが十分に簡単であれば、データのセキュリティにはそれほど厳格な要求があるわけではありません。ですので比較的簡単な暗号化である`base64`を採用することができます。このような方法は実装するのが比較的簡単で、Go言語の`base64`パッケージではすでにこれをよくサポートしています。下の例をご覧ください:
package main
import (
"encoding/base64"
"fmt"
)
func base64Encode(src []byte) []byte {
return []byte(base64.StdEncoding.EncodeToString(src))
}
func base64Decode(src []byte) ([]byte, error) {
return base64.StdEncoding.DecodeString(string(src))
}
func main() {
// encode
hello := "你好,世界! hello world"
debyte := base64Encode([]byte(hello))
fmt.Println(debyte)
// decode
enbyte, err := base64Decode(debyte)
if err != nil {
fmt.Println(err.Error())
}
if hello != string(enbyte) {
fmt.Println("hello is not equal to enbyte")
}
fmt.Println(string(enbyte))
}
## 高度な暗号化/復号
Go言語の`crypto`では双方向暗号の高度な暗号化/復号パッケージがあります:
- `crypto/aes`パッケージ:AES(Advanced Encryption Standard)は、Rijndael暗号化アルゴリズムとも呼ばれます。アメリカの連邦政府が採用しているブロック暗号の標準の一つです。
- `crypto/des`パッケージDES(Data Encryption Standard)は双方向暗号化標準のひとつです。これは現在秘密鍵のシステムに最も広く使用されています。特に金融データのセキュリティの保護で使われています。かつてアメリカ連邦政府の暗号化のスタンダードでしたがすでにAESにとってかわられています。
これらつのアルゴリズムは使用方法が似ていますので、ここではaesパッケージだけを例にこの使用を解説します。下の例をご覧ください
package main
import (
"crypto/aes"
"crypto/cipher"
"fmt"
"os"
)
var commonIV = []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f}
func main() {
// 暗号化したい文字列
plaintext := []byte("My name is Astaxie")
// 暗号化された文字列を渡すと、plaintは渡された文字列になります。
if len(os.Args) > 1 {
plaintext = []byte(os.Args[1])
}
// aesの暗号化文字列
key_text := "astaxie12798akljzmknm.ahkjkljl;k"
if len(os.Args) > 2 {
key_text = os.Args[2]
}
fmt.Println(len(key_text))
// 暗号化アルゴリズムaesを作成
c, err := aes.NewCipher([]byte(key_text))
if err != nil {
fmt.Printf("Error: NewCipher(%d bytes) = %s", len(key_text), err)
os.Exit(-1)
}
// 暗号化文字列
cfb := cipher.NewCFBEncrypter(c, commonIV)
ciphertext := make([]byte, len(plaintext))
cfb.XORKeyStream(ciphertext, plaintext)
fmt.Printf("%s=>%x\n", plaintext, ciphertext)
// 復号文字列
cfbdec := cipher.NewCFBDecrypter(c, commonIV)
plaintextCopy := make([]byte, len(plaintext))
cfbdec.XORKeyStream(plaintextCopy, ciphertext)
fmt.Printf("%x=>%s\n", ciphertext, plaintextCopy)
}
上では`aes.NewCipher`(引数keyはかならず16、24または32桁の[]byteとなります。それぞれAES-128, AES-192とAES-256アルゴリズムに対応します。)関数をコールすると`cipher.Block`インターフェースを返します。このインターフェースは3つの機能を実現します:
type Block interface {
// BlockSize returns the cipher's block size.
BlockSize() int
// Encrypt encrypts the first block in src into dst.
// Dst and src may point at the same memory.
Encrypt(dst, src []byte)
// Decrypt decrypts the first block in src into dst.
// Dst and src may point at the same memory.
Decrypt(dst, src []byte)
}
この3つの関数は暗号化/復号操作を実現します。詳細な操作は上の例をご覧ください。
## まとめ
この節ではいくつかの暗号化/復号アルゴリズムをご紹介しました。Webアプリケーションを開発している時は要求に合わせて異なる方法によって暗号化/復号を行うことができます。一般的なアプリケーションではbase64アルゴリズムを採用することができます。より高度な場合はaesやdesアルゴリズムを採用することができます。
## links
* [目次](<preface.md>)
* 前へ: [パスワードの保存](<09.5.md>)
* 次へ: [まとめ](<09.7.md>)

View File

@@ -1,2 +1,7 @@
<<<<<<< 380a8ee74c41759d8189ad553423467994187253
# Go Web プログラミング
Webプログラミングが好きでGo webプログラミングを書きました。皆さんに気にいってもらえれば幸いです。
=======
# Go Web プログラミング
Webプログラミングが好きでGo webプログラミングを書きました。皆さんに気にいってもらえれば幸いです。
>>>>>>> update the structure for gitbook

View File

@@ -1 +1 @@
../zh/build.go
../../ebook/build.go

View File

@@ -1 +1 @@
../zh/build.sh
../../ebook/build.sh

View File

Before

Width:  |  Height:  |  Size: 70 KiB

After

Width:  |  Height:  |  Size: 70 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 70 KiB

2
ja/src
View File

@@ -1 +1 @@
../zh/src
../../ebook/src