Xcode が 5 系にアップデートされ、Go 言語の設定が消えてしまいました。
Xcode 4 系と同じ方法で再び設定出来ました。
設定方法は過去の記事のままで大丈夫でした。
http://yokano-jp.blogspot.jp/2013/02/xcode4xgo.html
2013年11月1日金曜日
2013年10月29日火曜日
Google App Engine SDK for Go がアップデート
久しぶりにサーバのプログラムを書こうと思ったら、Google App Engine の Go SKD がアップデートされていました。Version 1.8 になってだいぶ変わっていました。
まず、ディレクトリ名が google_appengine から go_appengine に変わっていました。
今までは PHP だろうが Go だろうが同じ名前だったのですが、それぞれの言語でディレクトリ名が変わっているようです。
また、こちらは重要なのですが、
ローカルサーバ起動時に IP アドレスを指定するオプションが変わっていました。
これまでは -a オプションで
という風に IP アドレスを指定していたのですが、
これが --host オプションに変更されました。
これまでの -a オプションは使用できなくなっているので要注意です。 またサーバのログ出力フォーマットなど細かいところも色々と変わっていました。
まず、ディレクトリ名が google_appengine から go_appengine に変わっていました。
今までは PHP だろうが Go だろうが同じ名前だったのですが、それぞれの言語でディレクトリ名が変わっているようです。
また、こちらは重要なのですが、
ローカルサーバ起動時に IP アドレスを指定するオプションが変わっていました。
これまでは -a オプションで
dev_appserver.py -a 192.168.0.2 myapp
という風に IP アドレスを指定していたのですが、
これが --host オプションに変更されました。
dev_appserver.py --host 192.168.0.2 my app
これまでの -a オプションは使用できなくなっているので要注意です。 またサーバのログ出力フォーマットなど細かいところも色々と変わっていました。
2013年10月28日月曜日
Go で文字列をトリミングする
strings パッケージの Trim 関数を使って両端の文字をトリミングできます。
第2引数に取り除く対象の文字を複数指定できます。
第2引数に取り除く対象の文字を複数指定できます。
str := "___ABCD___" result := strings.Trim(str, "_") // "ABCD"
2013年9月7日土曜日
Google URL Shortener API を使う
Google URL Shortener API を使うと、
Web アプリから Google の URL 短縮サービスを使って、
URL を短くすることができます。
Google URL Shortener API
https://developers.google.com/url-shortener/
サービスを有効化する
画面左の Google API Console をクリック
Services -> URL Shorener API を ON に切り替えて利用規約に同意する
API キーを取得する
Web アプリから Google の URL 短縮サービスを使って、
URL を短くすることができます。
Google URL Shortener API
https://developers.google.com/url-shortener/
サービスを有効化する
画面左の Google API Console をクリック
Services -> URL Shorener API を ON に切り替えて利用規約に同意する
API キーを取得する
画面左のメニューから API Access をクリック
Simple API Access の API Key に描かれている文字列が API キー
URL を短くする
Web アプリケーションから以下のような HTTP リクエストを送信すると、
短縮された URL を含むレスポンスが帰ってきます。
データは送受信ともに JSON 形式です。
リクエスト
POST https://www.googleapis.com/urlshortener/v1/url Content-Type: application/json {"longUrl": "http://www.google.com/", "key": "APIキー"}
レスポンスボディ
{ "kind": "urlshortener#url", "id": "http://goo.gl/fbsS", "longUrl": "http://www.google.com/" }
Go 言語のサンプルです。通信は okalib を使っています。
// 短縮URLを取得する key := GOOGLE_API_KEY longUrl := Join("http://", HOSTNAME, "/runtime?game_key=", completeKey.Encode()) requestBody := Join(`{"key":"`, key, `","longUrl":"`, longUrl, `"}`) params := make(map[string]string, 1) params["Content-Type"] = "application/json" response := Request(this.c, "POST", "https://www.googleapis.com/urlshortener/v1/url", params, requestBody) responseBody := make([]byte, response.ContentLength) _, err = response.Body.Read(responseBody) Check(this.c, err) result := make(map[string]string, 3) err = json.Unmarshal(responseBody, &result) Check(this.c, err)
2013年8月19日月曜日
Go の Slice は参照型
Go 言語の Slice は代入すると参照が渡されます。
そのため、引数として渡した関数内での変更が、もとの Slice に影響します。
そのため、引数として渡した関数内での変更が、もとの Slice に影響します。
func addSlice(s []string) { s[1] = "WORLD" } func main() { s := make([]string, 2) s[0] = "HELLO" addSlice(s) log.Printf("SLICE: %v", s) // [HELLO WORLD] }
2013年8月18日日曜日
Go で構造体の要素に複数のタグを付ける
昨日の記事の通り、Go では構造体のプロパティにタグを付けることによってパッケージに動作を指示することができます。
複数のタグを1つの要素につける場合は、スペースで区切って指定することができます。
例えば、datastore には保存したくないけれど JSON の変換には含めて欲しい場合、
以下のように書くことができます。
複数のタグを1つの要素につける場合は、スペースで区切って指定することができます。
例えば、datastore には保存したくないけれど JSON の変換には含めて欲しい場合、
以下のように書くことができます。
type People struct { Name string `json:"name" datastore:"-"` // JSON には含めて datastore には含めない }
2013年8月17日土曜日
Go で構造体を JSON に変換するときのタグ付け
Go の構造体の各要素にはタグを付けることができます。
タグを付けることでパッケージに要素の扱い方を支持することができます。
例えば、 json パッケージを使って構造体を JSON に変換するときに使います。
タグに json: "-" を指定することで、変換時にこの要素を無視することを指示できます。
また、json: "名前" とすることで変換後の要素の名前を指定することもできます。
他にも Google App Engine の datastore パッケージなどで同じ書き方ができます。
詳しくはそれぞれのパッケージドキュメントを参照してください。
Package - Go
http://golang.org/pkg/
タグを付けることでパッケージに要素の扱い方を支持することができます。
type People struct { Id int `json:"-"` // id は変換後の json に含めない Name string `json:"name"` // Name は name として json 化 } people := new(People) people.Id = 1 people.Name = 'tanaka' bytes, err := json.Marshal(people) // bytes = {"name":"tanaka"}
例えば、 json パッケージを使って構造体を JSON に変換するときに使います。
タグに json: "-" を指定することで、変換時にこの要素を無視することを指示できます。
また、json: "名前" とすることで変換後の要素の名前を指定することもできます。
他にも Google App Engine の datastore パッケージなどで同じ書き方ができます。
詳しくはそれぞれのパッケージドキュメントを参照してください。
Package - Go
http://golang.org/pkg/
2013年8月15日木曜日
GAE + Go で指定した時刻に処理を実行する
Google App Engine では、taskqueue パッケージを使って指定した時刻に処理を実行することができます。「メールアドレスの仮登録後、24時間経っても本登録がされなかったらデータベースから削除する」みたいなときに便利です。
パッケージのインポート
タスクの作成
タスクは taskqueue.Task 型で表され、taskqueue.NewPOSTTask() 関数で作成できます。
タスクは、指定した URL に HTTP POST を送ることで実行されます。
ユーザからのアクセスと同様に handleFunc() 関数で処理を割り振ります。
url.Values 型で POST で引き渡すデータを指定できます。
また、 time.Duration 型で現在時刻からどれくらい後に実行するのかを指定できます。
ETA を使って実行時刻を直接指定することもできます。
実行時刻の指定がない場合、即時実行されます。
キューにタスクを追加
GAE ではアプリごとに複数のタスクキューを持つことができます。それぞれのタスクキューで、タスクを実行するタイミングや、キューの容量などを設定できます。
今回は最初から準備されている default という名前のキューにタスクを入れます。
default キューは実行できるタスクが無いか 5 秒毎にチェック・実行されます。
オリジナルのキューを作成する場合は queue.yaml を作って設定してください。
これで24時間後に実行されるタスクを作成できました。
URL を管理者専用にする
このままではユーザが /cancel にアクセスできてしまうので管理者専用にします。
開発サーバでタスクを手動実行する
ローカルの開発サーバでは、デバッグ用に手動でタスクを実行するツールも付いています。これを使わなくても自動実行はできますが、手動で実行したい場合は利用します。
http://localhost:8080/_ah/admin/queues
にアクセスすることでキューの状態や、タスクの実行が可能です。
Task Queue Go API Overview - Google App Engine
パッケージのインポート
import "appengine/taskqueue"
タスクの作成
タスクは taskqueue.Task 型で表され、taskqueue.NewPOSTTask() 関数で作成できます。
タスクは、指定した URL に HTTP POST を送ることで実行されます。
ユーザからのアクセスと同様に handleFunc() 関数で処理を割り振ります。
url.Values 型で POST で引き渡すデータを指定できます。
また、 time.Duration 型で現在時刻からどれくらい後に実行するのかを指定できます。
ETA を使って実行時刻を直接指定することもできます。
実行時刻の指定がない場合、即時実行されます。
// POST で渡すデータ values := url.Values{} values.Set("interim_key", key) // 24時間後に実行 delay, err := time.ParseDuration("24h") Check(c, err) // タスクの作成("/cancel" に POST で送信) task := taskqueue.NewPOSTTask("/cancel", values) task.Delay = delay
キューにタスクを追加
GAE ではアプリごとに複数のタスクキューを持つことができます。それぞれのタスクキューで、タスクを実行するタイミングや、キューの容量などを設定できます。
今回は最初から準備されている default という名前のキューにタスクを入れます。
default キューは実行できるタスクが無いか 5 秒毎にチェック・実行されます。
オリジナルのキューを作成する場合は queue.yaml を作って設定してください。
Go Task Queue Configuration - Google App Engineタスクは taskqueue.Add 関数でキューに追加できます。
// task を default キューに追加する taskqueue.Add(c, task, "default")
これで24時間後に実行されるタスクを作成できました。
URL を管理者専用にする
このままではユーザが /cancel にアクセスできてしまうので管理者専用にします。
GAE + Go で管理者専用機能を作る - y.okano blogを参考に app.yaml で login: admin を指定しておきます。
開発サーバでタスクを手動実行する
ローカルの開発サーバでは、デバッグ用に手動でタスクを実行するツールも付いています。これを使わなくても自動実行はできますが、手動で実行したい場合は利用します。
http://localhost:8080/_ah/admin/queues
にアクセスすることでキューの状態や、タスクの実行が可能です。
2013年7月26日金曜日
GAE + Go でホスト名を取得する
サーバのホスト名を以下のように取得出来ます。
詳しくはこちらのドキュメントを参照してください
The appengine package - Google App Engine
c := appengine.NewContext(r) hostname := appengine.DefaultVersionHostName(c) c.Debugf("HOSTNAME: %s", hostname)
詳しくはこちらのドキュメントを参照してください
The appengine package - Google App Engine
2013年7月22日月曜日
GAE + Go で Sign in with Facebook (2)
前回は Facebook にアプリを登録して Client ID と Client Secret を発行してもらいました。
GAE + Go で Sign in with Facebook
続いて実際にコードを書いていきます。
ちなみに今回は OAuth 2.0 の認証コード方式を使います。
まずログインボタンを設置します。
ボタンの画像はサードパーティから無料で提供されているものを使用しました。
リンク先を /login_facebook とします。
/login_facebook に対応するハンドラを作成します。
http.HandleFunc から呼び出します。
Facebook から発行された Client ID とClient Secret を使って通信します。
最初に、アプリがユーザデータへアクセスする許可をユーザから得る必要があります。
Facebook ではユーザの許可を得る画面を OAuth Dialog と読んでいます。
OAuth Dialog の URL は http://www.facebook.com/dialog/oauth です。
ここに Client ID, Client Secret, 許可をもらった時のリダイレクト URL を GET で渡します。
詳しくはこちらをご覧ください
OAuth Dialog - Facebook Developers
上のコードでは自作のライブラリを使用しています。
中身はこんな感じになっています。
今回はリダイレクト先として http://escape-3ds.appspot.com/callback_facebook を設定しました。
自分のアプリに合わせてコールバック先の URL を設定してください。
コールバックされた後の処理を書きます。
こちらも http.HandleFunc() で呼び出されるようにしましょう。
ユーザからの許可が得られたら、アクセストークンを Facebook に要求します。
上のコードでは RequestFacebookToken() で要求しています。
このとき、ユーザIDとユーザ名が含まれたレスポンスが Facebook から返されます。
データベース上にユーザID が存在するかどうかを調べて、新規ユーザかどうかを判断しています。
アクセストークンの取得先 URL は https://graph.facebook.com/oauth/access_token です。
アクセストークンについてはこちら
Access Tokens - Facebook Developer
RequestFacebookToken() の中身はこんな感じ。
RequestAccessToken() でアクセストークンとユーザ情報を取得して、
レスポンスのユーザデータのパースしています。
RequestAccessToken() の中身はこんな感じ。
すべてのコードは GitHub においてあります。
https://github.com/yokano/escape3ds
OAuth 2.0 に関するコントローラは
server/controller/controller.go
server/controller/oauth.go
ライブラリは
server/lib/oauth2.go
にあります。
GAE + Go で Sign in with Facebook
続いて実際にコードを書いていきます。
ちなみに今回は OAuth 2.0 の認証コード方式を使います。
まずログインボタンを設置します。
ボタンの画像はサードパーティから無料で提供されているものを使用しました。
リンク先を /login_facebook とします。
<a href="/login_facebook"><img src="/client/login/img/sign_in_with_facebook.png"></a>
/login_facebook に対応するハンドラを作成します。
http.HandleFunc から呼び出します。
// Facebook のログインボタンが押された時の処理 func (this *Controller) LoginFacebook(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) oauth := NewOAuth2(c, FACEBOOK_CLIENT_ID, FACEBOOK_CLIENT_SECRET) oauth.RequestAuthorizationCode(w, r, "https://www.facebook.com/dialog/oauth", url.QueryEscape("http://escape-3ds.appspot.com/callback_facebook")) }
Facebook から発行された Client ID とClient Secret を使って通信します。
最初に、アプリがユーザデータへアクセスする許可をユーザから得る必要があります。
Facebook ではユーザの許可を得る画面を OAuth Dialog と読んでいます。
OAuth Dialog の URL は http://www.facebook.com/dialog/oauth です。
ここに Client ID, Client Secret, 許可をもらった時のリダイレクト URL を GET で渡します。
詳しくはこちらをご覧ください
OAuth Dialog - Facebook Developers
中身はこんな感じになっています。
// OAuth 2.0 type OAuth2 struct { context appengine.Context clientId string clientSecret string } // OAuth2.0 インスタンスを返す func NewOAuth2(c appengine.Context, clientId string, clientSecret string) *OAuth2 { oauth := new(OAuth2) oauth.context = c oauth.clientId = clientId oauth.clientSecret = clientSecret return oauth } // 認証コードをリクエストする // 認証ページヘのリダイレクトを行いユーザに認証してもらう // 認証が完了したらリダイレクトURIへ認証コードが返ってくる func (this *OAuth2) RequestAuthorizationCode(w http.ResponseWriter, r *http.Request, targetUri string, redirectUri string) { targetUri = fmt.Sprintf("%s?client_id=%s&redirect_uri=%s&response_type=code", targetUri, this.clientId, redirectUri) http.Redirect(w, r, targetUri, 302) }
今回はリダイレクト先として http://escape-3ds.appspot.com/callback_facebook を設定しました。
自分のアプリに合わせてコールバック先の URL を設定してください。
コールバックされた後の処理を書きます。
こちらも http.HandleFunc() で呼び出されるようにしましょう。
// Facebook でユーザがアクセスを許可した時に呼び出されるコールバック関数 func (this *Controller) CallbackFacebook(w http.ResponseWriter, r*http.Request) { c := appengine.NewContext(r) userInfo := this.RequestFacebookToken(w, r) model := NewModel(c) view := NewView(c, w) key := "" if model.ExistOAuthUser("Facebook", userInfo["oauth_id"]) { // 既存ユーザ params := make(map[string]string, 2) params["OAuthId"] = userInfo["oauth_id"] params["Type"] = "Facebook" key = model.GetUserKey(params) } else { // 新規ユーザ params := make(map[string]string, 4) params["user_type"] = "Facebook" params["user_name"] = userInfo["name"] params["user_oauth_id"] = userInfo["oauth_id"] params["user_pass"] = "" user := model.NewUser(params) key = model.AddUser(user) } if this.GetSession(c, r) == "" { this.StartSession(w, r, key) } view.Gamelist(key) }
ユーザからの許可が得られたら、アクセストークンを Facebook に要求します。
上のコードでは RequestFacebookToken() で要求しています。
このとき、ユーザIDとユーザ名が含まれたレスポンスが Facebook から返されます。
データベース上にユーザID が存在するかどうかを調べて、新規ユーザかどうかを判断しています。
アクセストークンの取得先 URL は https://graph.facebook.com/oauth/access_token です。
アクセストークンについてはこちら
Access Tokens - Facebook Developer
RequestFacebookToken() の中身はこんな感じ。
// Facebook へアクセストークンを要求する。 // この関数は Facebook から認証コードをリダイレクトで渡された時に呼ばれる。 // ユーザ情報を格納した map を返す。 func (this *Controller) RequestFacebookToken(w http.ResponseWriter, r *http.Request) map[string]string { c := appengine.NewContext(r) code := r.FormValue("code") oauth := NewOAuth2(c, FACEBOOK_CLIENT_ID, FACEBOOK_CLIENT_SECRET) token := oauth.RequestAccessToken(w, r, "https://graph.facebook.com/oauth/access_token", url.QueryEscape("http://escape-3ds.appspot.com/callback_facebook"), code) response := oauth.RequestAPI(w, "https://graph.facebook.com/me", token) // JSON を解析 type UserInfo struct { Id string `json:"id"` Name string `json:"name"` } userInfo := new(UserInfo) err := json.Unmarshal(response, userInfo) Check(c, err) result := make(map[string]string, 2) result["oauth_id"] = userInfo.Id result["name"] = userInfo.Name return result }
RequestAccessToken() でアクセストークンとユーザ情報を取得して、
レスポンスのユーザデータのパースしています。
RequestAccessToken() の中身はこんな感じ。
// アクセストークンをリクエストする // 引き換えとして認証コードを渡すこと func (this *OAuth2) RequestAccessToken(w http.ResponseWriter, r *http.Request, targetUri string, redirectUri string, code string) string { targetUri = fmt.Sprintf("%s?client_id=%s&redirect_uri=%s&client_secret=%s&code=%s", targetUri, this.clientId, redirectUri, this.clientSecret, code) params := make(map[string]string, 4) params["client_id"] = this.clientId params["redirect_uri"] = redirectUri params["client_secret"] = this.clientSecret params["code"] = code response := Request(this.context, "GET", targetUri, params, "") body := make([]byte, 1024) _, err := response.Body.Read(body) Check(this.context, err) // response: oauth_token=******&expires=****** responseParams := strings.Split(string(body), "&") tokenParam := strings.Split(responseParams[0], "=") return tokenParam[1] }
すべてのコードは GitHub においてあります。
https://github.com/yokano/escape3ds
OAuth 2.0 に関するコントローラは
server/controller/controller.go
server/controller/oauth.go
ライブラリは
server/lib/oauth2.go
にあります。
2013年7月20日土曜日
GAE + Go で Sign in with Facebook(1)
以前 GAE + GO で Twitter ログインの記事を書きましたが、今回は Facebook d
GAE + Go で Sign in with Twitter - y.okano blog
Facebook ログイン関係の公式ドキュメントはこちら
Facebook Login - facebook developers
Twitter は OAuth 1.0 を採用していますが、Facebook では OAuth 2.0 になります。
OAuth Core 1.0 Revision A - oauth.net
OAuth 2.0 - rfc6749
Facebook からは JavaScript でログインが可能な SDK が提供されています。
今回はサーバサイドでログインを実装するので、JavaScript SDK は使用しません。
JavaScript SDK を使ったログイン方法についてはこちら
The Login Flow for Web - facebook developers
JavaScript SDK を使わないログイン方法についてはこちら
The Login Flow for Web (without JavaScript SDK)
アプリの登録
まず、Facebook に自作のアプリを登録します。
Facebook のアプリ管理ページを開きます。
アプリ - facebook developers
右上の「+新しいアプリを作成」ボタンを押すと以下の様なダイアログが出ます。
アプリを登録したら、自動的にアプリの基本設定が表示されます。
ここに表示される App ID と App Secret をログインに使用します。
App Domains に GAE のアプリのドメイン名を入力します。
appname.appspot.com という感じです。
更に画面下の「アプリを Facebook に結合する方法を選択」部分を変更します。
「Facebook でログインするウェブサイト」のサイト URL を入力します。
http://appname.appspot.com/ という感じです。
ここまで変更できたら「変更を保存」ボタンを押して保存します。
これで Facebook でログインするためのアプリ登録が完了です。
今日はここまで。
GAE + Go で Sign in with Twitter - y.okano blog
Facebook ログイン関係の公式ドキュメントはこちら
Facebook Login - facebook developers
OAuth Core 1.0 Revision A - oauth.net
OAuth 2.0 - rfc6749
Facebook からは JavaScript でログインが可能な SDK が提供されています。
今回はサーバサイドでログインを実装するので、JavaScript SDK は使用しません。
JavaScript SDK を使ったログイン方法についてはこちら
The Login Flow for Web - facebook developers
JavaScript SDK を使わないログイン方法についてはこちら
The Login Flow for Web (without JavaScript SDK)
アプリの登録
まず、Facebook に自作のアプリを登録します。
Facebook のアプリ管理ページを開きます。
アプリ - facebook developers
右上の「+新しいアプリを作成」ボタンを押すと以下の様なダイアログが出ます。
Display Name, App Category を入力します。
App Namespace は入力しなくて OK です。
Web Hosting は GAE を使うためチェックは外した状態にします。
アプリを登録したら、自動的にアプリの基本設定が表示されます。
ここに表示される App ID と App Secret をログインに使用します。
App Domains に GAE のアプリのドメイン名を入力します。
appname.appspot.com という感じです。
更に画面下の「アプリを Facebook に結合する方法を選択」部分を変更します。
「Facebook でログインするウェブサイト」のサイト URL を入力します。
http://appname.appspot.com/ という感じです。
ここまで変更できたら「変更を保存」ボタンを押して保存します。
これで Facebook でログインするためのアプリ登録が完了です。
今日はここまで。
2013年7月14日日曜日
GAE + Go で管理者専用機能を作る
GAE + Go でデバッグツールや、データの削除ツールなどをアプリ内に同梱する場合、
該当する URL パターンを管理者専用にできます。
app.yaml を開き、管理者専用にしたい URL に login: admin を指定します。
login: admin に設定した URL へアクセスしようとすると、
以下のようにログインページヘ遷移され、アプリ管理者のログインを求められます。
(写真は認証方式を Google アカウントにしている場合です)
ちなみにローカル開発環境では以下の様なフォームが出力されます。
"Sign in as Administrator" にチェックを入れると認証が通ります。
デバッグ用のページは管理者専用に設定しましょう。
詳しくは公式のドキュメントをご覧ください。
Requiring Login or Administrator Status - Google App Engine https://developers.google.com/appengine/docs/go/config/appconfig#Requiring_Login_or_Administrator_Status
該当する URL パターンを管理者専用にできます。
app.yaml を開き、管理者専用にしたい URL に login: admin を指定します。
application: appname version: 0 runtime: go api_version: go1 handlers: # 管理者専用の API を設定 # - url: /debug login: admin script: _go_app - url: /.* script: _go_app
login: admin に設定した URL へアクセスしようとすると、
以下のようにログインページヘ遷移され、アプリ管理者のログインを求められます。
(写真は認証方式を Google アカウントにしている場合です)
ちなみにローカル開発環境では以下の様なフォームが出力されます。
"Sign in as Administrator" にチェックを入れると認証が通ります。
デバッグ用のページは管理者専用に設定しましょう。
詳しくは公式のドキュメントをご覧ください。
Requiring Login or Administrator Status - Google App Engine https://developers.google.com/appengine/docs/go/config/appconfig#Requiring_Login_or_Administrator_Status
2013年7月13日土曜日
godoc で Go のドキュメントを生成する
Java には JavaDoc, JavaScript には JSDoc がありますが、
Go には公式のドキュメント生成ツールとして godoc があります。
Godoc: documenting Go code
http://golang.org/doc/articles/godoc_documenting_go_code.html
GAE の SDK for Go を入れていればそのまま使えます。
しかし、このままではスタイルや JavaScript が参照されていません。
デフォルトの HTML テンプレート内で CSS や JS を参照していないためです。
テンプレートはSDK 内の goroot/lib/godoc/godoc.html が使われます。
CSS と JS は以下にあります。
goroot/doc/style.css
goroot/doc/godoc.js
テンプレートのHTMLからこれらのファイルを参照すると、
公式サイトと同じデザインになります。
あとは、必要に応じてスタイルを編集すれば OK です。
私の場合は、 <frameset> を使ってこんな感じのテンプレートを作りました。
godoc はファイルの先頭部分や、関数名の直前に書かれたコメントを拾ってくれます。
/* */ ではなく // を使うのが一般的なようです。
ついでに、godoc を生成するシェルスクリプトを書いておき、
コミット前に実行すると常に最新のドキュメントがプログラムに同梱できて便利です。
godoc.sh
ちなみに、godoc とは別に GitHub のリポジトリの URL を貼り付けると、
自動的にドキュメントを生成してくれる Web サービスなどもあるようです。
自分でテンプレートを作るのが面倒なときはこっちのほうがいいかも。
GoDoc
http://godoc.org
Go には公式のドキュメント生成ツールとして godoc があります。
Godoc: documenting Go code
http://golang.org/doc/articles/godoc_documenting_go_code.html
GAE の SDK for Go を入れていればそのまま使えます。
$ godoc -html ./model > model.html出力された HTML は下の写真です。
しかし、このままではスタイルや JavaScript が参照されていません。
デフォルトの HTML テンプレート内で CSS や JS を参照していないためです。
テンプレートはSDK 内の goroot/lib/godoc/godoc.html が使われます。
CSS と JS は以下にあります。
goroot/doc/style.css
goroot/doc/godoc.js
テンプレートのHTMLからこれらのファイルを参照すると、
公式サイトと同じデザインになります。
あとは、必要に応じてスタイルを編集すれば OK です。
私の場合は、 <frameset> を使ってこんな感じのテンプレートを作りました。
godoc はファイルの先頭部分や、関数名の直前に書かれたコメントを拾ってくれます。
/* */ ではなく // を使うのが一般的なようです。
ついでに、godoc を生成するシェルスクリプトを書いておき、
コミット前に実行すると常に最新のドキュメントがプログラムに同梱できて便利です。
godoc.sh
#!/bin/sh godoc -html ./server > ./document/server/server.html godoc -html ./server/config > ./document/server/config.html godoc -html ./server/controller > ./document/server/controller.html godoc -html ./server/model > ./document/server/model.html godoc -html ./server/view > ./document/server/view.html godoc -html ./server/lib > ./document/server/lib.html
実行
$ sh godoc.sh
ちなみに、godoc とは別に GitHub のリポジトリの URL を貼り付けると、
自動的にドキュメントを生成してくれる Web サービスなどもあるようです。
自分でテンプレートを作るのが面倒なときはこっちのほうがいいかも。
GoDoc
http://godoc.org
2013年7月9日火曜日
GAE + Go で他ディレクトリの go ファイルを読み込む
GAE + Go では import 文で他のディレクトリ内の go ファイルを読み込むことができます。
import 文でアプリケーションルートディレクトリから、
読み込みたい go ファイルが置いてあるディレクトリまでを指定することで、
対象ディレクトリ内のすべての go ファイルを読み込むことができます。
例えば以下の様な分割をしていたとします。
view 内の go ファイルから model 内の go ファイルを参照するとします。
以下のように import 文を書きます。
view/hoge.go
package をインポートしたときと同様に、
関数や変数を使うときには読み込んだディレクトリ名を先頭に付けます。
先頭にディレクトリ名を付けたくない場合は、以下のように読みこめばOKです。
また、パッケージと同様で、
関数名や変数名は大文字で始まるものだけが外部から参照できます。
小文字で始まる関数を別のファイルから使うことはできないので注意が必要です。
import 文でアプリケーションルートディレクトリから、
読み込みたい go ファイルが置いてあるディレクトリまでを指定することで、
対象ディレクトリ内のすべての go ファイルを読み込むことができます。
例えば以下の様な分割をしていたとします。
view 内の go ファイルから model 内の go ファイルを参照するとします。
以下のように import 文を書きます。
view/hoge.go
package gae // approot 直下の model ディレクトリ内のすべての go ファイルを読み込む import "model" func showModel() { data := model.GetData() fmt.Fprintf("Data is %s", data.ToString()) }
package をインポートしたときと同様に、
関数や変数を使うときには読み込んだディレクトリ名を先頭に付けます。
data := model.GetData()
先頭にディレクトリ名を付けたくない場合は、以下のように読みこめばOKです。
package gae import . "model" func showModel() { data := GetData() fmt.Fprintf("Data is %s", ToString()) }
また、パッケージと同様で、
関数名や変数名は大文字で始まるものだけが外部から参照できます。
小文字で始まる関数を別のファイルから使うことはできないので注意が必要です。
2013年7月5日金曜日
Go + GAE で HTML テンプレート内に変数を展開
HTML テンプレート内に以下のような {{}} 構文を書くと変数を展開することができます。
昨日のコードをそのまま編集します。
html
go
昨日のコードをそのまま編集します。
html
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello Template!</title> </head> <body> <h1>Hello Template!</h1> <div> 私の名前は {{.Name}} です。 </div> </body> </html>
go
package helloworld import ( "net/http" "html/template" ) func init() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { t, err := template.ParseFiles("app/template.html") if err == nil { contents := make(map[string]string, 1) contents["Name"] = "y.okano" t.Execute(w, contents) } }) }
構造体やマップを作って template.Execute() に渡すと該当する変数を探して展開してくれます。
2013年7月4日木曜日
Go + GAE で HTML ファイルを表示
Go + GAE で HTML ファイルを表示する方法です。
環境構築は昨日の記事をご覧ください。
http://yokano-jp.blogspot.jp/2013/07/google-app-engine-go.html
HTML ファイルを作成
画面に表示される HTML ファイルを作成します。
今回は ApplicationRoot/app/template.html として作成しました。
HTML ファイルを表示
Go のスクリプトを以下のように編集します
これで localhost:8080 へアクセスすると HTML ファイルが表示されます。
環境構築は昨日の記事をご覧ください。
http://yokano-jp.blogspot.jp/2013/07/google-app-engine-go.html
HTML ファイルを作成
画面に表示される HTML ファイルを作成します。
今回は ApplicationRoot/app/template.html として作成しました。
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>Hello Template!</title> </head> <body> <h1>Hello Template!</h1> <div> HTML ファイルを出力するテストです </div> </body> </html>
HTML ファイルを表示
Go のスクリプトを以下のように編集します
package helloworld import ( "net/http" "html/template" ) func init() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { t, err := template.ParseFiles("app/template.html") if err == nil { t.Execute(w, nil) } }) }
これで localhost:8080 へアクセスすると HTML ファイルが表示されます。
2013年7月3日水曜日
Google App Engine + Go の開発環境構築
Google App Engine では無料でウェブアプリをホスティングすることができます。
ターミナルを開きます。
GAE/ フォルダまで移動して、以下を実行します。
エラーがなければ開発サーバが起動します。
ターミナルにはサーバのログが表示され続けます。
⌘ + C でサーバを終了出来ます。
サーバが起動している状態で Web ブラウザで
http://localhost:8080/
にアクセスすると Hello World! と表示されます。
これで開発環境の構築は完了です。
また、データベースやユーザ管理など便利な機能が色々と付いています。
サーバサイドとして使える言語は Java, Python, Go, PHP です。
今回は Go を使った場合の開発環境の整え方です。
Python のインストール
まず、Python をインストールします。
GAE の SDK に Python スクリプトが含まれているため必要となります。
Mac OS X の場合はデフォルトでインストールされているので不用です。
Windows を使っている場合は以下からダウンロード、インストールしてください。
Python.org
SDK のインストール
GAE の開発キットをインストールします。
公式サイトの Downloads をクリックして SDK のダウンロードをしてください。
Google App Engine - Google Developers
PHP, Python, Java, Go 用の4種類があるので Go を落とします。
公式サイトの Downloads をクリックして SDK のダウンロードをしてください。
Google App Engine - Google Developers
PHP, Python, Java, Go 用の4種類があるので Go を落とします。
また、OS 毎に SDK が異なるので自分の OS に合わせてダウンロードして下さい。
zip を展開すると google_appengine というフォルダが出来ます。
フォルダを好きな場所に置き、パスを通しておいてください。
Mac なら Application ディレクトリに入れておけば OK です。
ターミナルを開いて以下のコマンドが実行できるか確認します。
何かしら表示されれば OK です。
$ dev_appserver.py
Hello World!
GAE の開発用ローカルサーバを立てて Go から Hello World! します。
好きな場所に GAE フォルダを作成し、その中に helloworld フォルダを作成します。
helloworld フォルダの中身が Web アプリになります。
GAE フォルダは Web アプリをまとめておくために作っています。
helloworld フォルダ内に app.yaml という名前のファイルを作成します。
これは Web アプリの設定ファイルです。
app.yaml 内に以下をコピペします。
helloworld フォルダ内に app フォルダを作成します。
app フォルダの中に helloworld.go を作成します。
go スクリプトはサブディレクトリ内に置かなければならないので、appフォルダを作成しました。
helloworld.go に以下をコピペします。
好きな場所に GAE フォルダを作成し、その中に helloworld フォルダを作成します。
helloworld フォルダの中身が Web アプリになります。
GAE フォルダは Web アプリをまとめておくために作っています。
helloworld フォルダ内に app.yaml という名前のファイルを作成します。
これは Web アプリの設定ファイルです。
app.yaml 内に以下をコピペします。
application: helloworld version: 1 runtime: go api_version: go1 handlers: - url: /.* script: _go_app
helloworld フォルダ内に app フォルダを作成します。
app フォルダの中に helloworld.go を作成します。
go スクリプトはサブディレクトリ内に置かなければならないので、appフォルダを作成しました。
helloworld.go に以下をコピペします。
package helloworld import ( "net/http" "fmt" ) func init() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello World!") }) }
ターミナルを開きます。
GAE/ フォルダまで移動して、以下を実行します。
$ dev_appserver.py helloworld
エラーがなければ開発サーバが起動します。
ターミナルにはサーバのログが表示され続けます。
⌘ + C でサーバを終了出来ます。
サーバが起動している状態で Web ブラウザで
http://localhost:8080/
にアクセスすると Hello World! と表示されます。
これで開発環境の構築は完了です。
2013年7月1日月曜日
Go の template パッケージと AngularJS の共存
AngularJS では HTML 内に {{}} で囲まれた部分を Angular 文として処理します。
一方、Go の template パッケージも {{}} で囲まれた部分を Go のコードとして処理します。
この2つが衝突してエラーが起きます。
GAE + Go では予め作っておいた HTML テンプレートに変数を展開するのが基本です。
このとき、HTML 内の変数が入る部分に {{.変数名}} という形式で表現します。
一方、AngularJS でも同様に HTML 内に Model の変数を当てはめて出力します。
書式も同じで HTML に {{変数名}} という形式で表現します。
AngularJS の変数を出力するために {{変数名}} を HTML テンプレートに埋め込むと、
Go が「これは Go の変数名だ」と勘違いして変数を探しに行きます。
Go 内で定義されていない変数を参照しようとするため nil pointer エラーが発生します。
衝突を回避するために AngularJS で {{}} を別の記号に変更できます。
これで {{変数名}} が Go の変数を、 {[{変数名}]} が JS の変数を指すようになります。
一方、Go の template パッケージも {{}} で囲まれた部分を Go のコードとして処理します。
この2つが衝突してエラーが起きます。
GAE + Go では予め作っておいた HTML テンプレートに変数を展開するのが基本です。
このとき、HTML 内の変数が入る部分に {{.変数名}} という形式で表現します。
一方、AngularJS でも同様に HTML 内に Model の変数を当てはめて出力します。
書式も同じで HTML に {{変数名}} という形式で表現します。
AngularJS の変数を出力するために {{変数名}} を HTML テンプレートに埋め込むと、
Go が「これは Go の変数名だ」と勘違いして変数を探しに行きます。
Go 内で定義されていない変数を参照しようとするため nil pointer エラーが発生します。
runtime error: invalid memory address or nil pointer dereference
衝突を回避するために AngularJS で {{}} を別の記号に変更できます。
app.config(function($interpolateProvider) { $interpolateProvider.startSymbol('{[{'); $interpolateProvider.endSymbol('}]}'); });
これで {{変数名}} が Go の変数を、 {[{変数名}]} が JS の変数を指すようになります。
2013年6月30日日曜日
Go の template パッケージで map の key を参照する
GAE + Go では HTML を html/template パッケージで出力することが基本になります。
このとき {{}} 構文によって Go 内の変数を HTML 内に展開することができます。
array や map や slice の中身を順次取り出しながら表示する場合は
{{range}}{{end}} 構文を使って書くことができます。
ただ中身を表示するだけならこれでよいのですが、
map を使っている場合、どうしても key を埋め込みたい時があるでしょう。
(クリックした要素の key をサーバへ返したいときなど)
この場合は以下のように for each 文っぽく key とvalue を変数に入れることができます。
ちなみに $val は無くても同じように動きます。
地味に 100 本目の投稿です。
このとき {{}} 構文によって Go 内の変数を HTML 内に展開することができます。
array や map や slice の中身を順次取り出しながら表示する場合は
{{range}}{{end}} 構文を使って書くことができます。
<ul> {{range .}} <li>{{.Name}}さんこんにちは</li> {{end}} </ul>
ただ中身を表示するだけならこれでよいのですが、
map を使っている場合、どうしても key を埋め込みたい時があるでしょう。
(クリックした要素の key をサーバへ返したいときなど)
この場合は以下のように for each 文っぽく key とvalue を変数に入れることができます。
<ul id="gamelist"> {{range $key, $val := .}} <li class="game" key="{{$key}}"> <div class="title">{{$val.Name}}</div> <div class="description">{{$val.Description}}</div> <div class="thumbnail"><img width="200" src="/client/img/living.png"></div> <a href="/editor?game_key={{$key}}"><button class="edit">作る</button></a> <button class="copy">コピー</button> <button class="delete">消す</button> </li> {{end}} </ul>
ちなみに $val は無くても同じように動きます。
地味に 100 本目の投稿です。
2013年6月28日金曜日
GAE + Go でログを取る
GAE + Go では appengine パッケージにログを取る命令が入っています。
The appengine package - Google App Engine
https://developers.google.com/appengine/docs/go/reference
c.Infof() や Debugf() でログを取ることができます。
ローカル開発よサーバの場合、コマンドプロンプトにログが出力されます。
本番環境の場合はアプリ管理画面にログが出力されます。
Debug だけ表示、Error だけ表示などのように絞込みも可能です。
The appengine package - Google App Engine
https://developers.google.com/appengine/docs/go/reference
import ( "appengine" "net/http" ) func init() { http.HandleFunc("/", debug) } func debug(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) c.Debugf("Debug") c.Infof("Infomation") c.Warningf("Warning") c.Criticalf("Critical") }
c.Infof() や Debugf() でログを取ることができます。
ローカル開発よサーバの場合、コマンドプロンプトにログが出力されます。
本番環境の場合はアプリ管理画面にログが出力されます。
Debug だけ表示、Error だけ表示などのように絞込みも可能です。
登録:
投稿 (Atom)