2011年12月20日火曜日

new関数とmake関数について


私が書いたGo言語プログラミング入門 on Google App Engineにある記述で間違いがあったのですが、正誤表に書くには長いので、この記事に残しておこうと思います。

P.125のnew関数とmake関数の使い分けの所で、
次のように間違った例を掲載しています。

intArray := new([]int)
fmt.Fprintf(w, "%d¥n", intArray[0])

これは、そもそも書き方が間違っているという指摘を受けまして、
確認をしてみました。結論は間違ってます。

new([]int)が返す型は「*[]int」型です。int型配列に対するポインタが返されます。
しかも、配列の長さを指定していませんので、配列の長さが0です。
中身がありません。

したがって、intArray[0]と書くのは間違いで、(*intArray)[0]と書くのが
正しい表記となりますが、配列の中身がないので、実行時にエラーになります。

しかし、次のように、配列の長さを指定した形で使えば実行時エラーにはならなくなります。

intArray := new([5]int)
fmt.Fprintf(w, "%d¥n", (*intArray)[0])
検証したプログラムも掲載しておきます。
検証したバージョンはVer.1.6.1ですが、未検証ですが1.5.5でも問題ないと思います。

package newsample

import (
 "fmt"
 "http"
)

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
// 書籍の例は間違い!
// intArray := new([]int)
//
// fmt.Fprintf(w, "%d\n", intArray[0])

 intArray := new([5]int)

 fmt.Fprintf(w, "%d\n", (*intArray)[0])

 intArray2 := make([]int, 5)

 fmt.Fprintf(w, "%d\n", intArray2[0]) 
}


new関数の使い方について認識不足でした。
今回も柴田芳樹さんにご指摘いただきました。本当にありがとうございました。

GoのTypeAssertion(型変換?)


私が書いたGo言語プログラミング入門 on Google App Engineにある記述で間違いがあったのですが、正誤表に書くには長いので、この記事に残しておこうと思います。

P.108で「インターフェイスの型の変数に値を代入した後、本来の型に戻す事はできません。」と記述しているのですが、実際は、戻すことが可能です。
具体的な方法は、"変数名.(型)"と記述することで復元します。
Go言語の言語仕様にも、Primary expressionsに記載がありました。

実際の検証用のソースコードです。
動作確認はSDK1.6.1で行いましたので、書籍のベースバージョン1.5.5では未検証ですが、
古いバージョンのSDKで開発される事は減るかと思いますので、検証していません。

以下のソースコードが検証用です。(ほぼツッコミ時に紹介されたソースのままですが…)

package interfacesample3

import (
 "fmt"
 "http"
)

type Introduction interface {
 intro(w http.ResponseWriter)
}

type Coffee struct {
 Sugar bool
}

func (coffee Coffee) intro(w http.ResponseWriter) {
 if coffee.Sugar {
  fmt.Fprintf(w, "This is a coffee with sugar\n")
 } else {
  fmt.Fprintf(w, "This is a black coffee\n")
 }
}

func init() {
 http.HandleFunc("/", handler)
}

func handler(w http.ResponseWriter, r *http.Request) {
        // Introduction型の配列を作成し、Coffee型のインスタンスを代入する。
 array := make([]Introduction, 1)
 array[0] = new(Coffee)
 array[0].intro(w)

        // そもそもnew関数で返される型はCoffeeではなく、*Coffee!
 var coffee *Coffee
 coffee = array[0].(*Coffee)
 coffee.Sugar = true
 coffee.intro(w)
}

出力結果は
This is a black coffee
This is a coffee with sugar

となり、復元できている事がわかります。

書籍の型の復元については、完全に不勉強でした。
今回は柴田芳樹さんにご指摘いただきました。本当にありがとうございました。

2011年12月18日日曜日

Goでの日付変換

私が書いたGo言語プログラミング入門 on Google App Engineにも記述していないので、ここに載せておきたいと思います。

書籍内だとデータストアに日付を登録する時に、以下のような記述をしています。

datastore.SecondsToTime(time.Seconds())

これは、現在日時が取得されて日付がdatastore.Time型(中身は整数)に変換されます。
確かに現在日時であれば、これで良いのですが、指定した日時を格納したい場合に
この方法では日時のデータに変換することができません。
したがって、他の言語と同様に、文字列から日時データに変換します。
以下のような記述にします。

strdate := "2011-12-18 23:00:00"
inputtime := time.Parse("2006-01-02 15:04:05", startdatestr)
datastore.SecondsToTime(inputtime.Seconds())

これは、年:4桁、月:2桁、日:2桁、24時間表記の時間、2桁の分、2桁の秒となります。

time.Parse関数の第1引数がフォーマットを指定するのですが、標準で用意されている
フォーマットもあります。以下、timeパッケージのformat.goからの抜粋です。

const (
ANSIC    = "Mon Jan _2 15:04:05 2006"
  UnixDate = "Mon Jan _2 15:04:05 MST 2006"
RubyDate = "Mon Jan 02 15:04:05 -0700 2006"
RFC822   = "02 Jan 06 1504 MST"
// RFC822 with Zulu time.
RFC822Z = "02 Jan 06 1504 -0700"
RFC850  = "Monday, 02-Jan-06 15:04:05 MST"
RFC1123 = "Mon, 02 Jan 2006 15:04:05 MST"
RFC3339 = "2006-01-02T15:04:05Z07:00"
Kitchen = "3:04PM"
// Handy time stamps.
Stamp      = "Jan _2 15:04:05"
StampMilli = "Jan _2 15:04:05.000"
StampMicro = "Jan _2 15:04:05.000000"
StampNano  = "Jan _2 15:04:05.000000000"
)

RFC準拠のフォーマットであれば、"RFC3339"などと指定することで書式に合わせて文字列を解析し、変換してくれます。

JavaやC#などと違って"yyyy/MM/dd HH:mm:ss"というフォーマットが指定できないのが大変ですが、慣れると意外と良いかもしれません。

2011年12月16日金曜日

Go言語プログラミング入門(正誤表)

そろそろ(12/16時点)私の2冊目の書籍、「Go言語プログラミング入門 on Google App Engine」が発売されて、手元に届いた頃だと思うので、読者の方からの指摘、自分自身で発見した誤りをメモしておきたいと思います。
正式な発表は出版社のサイトを御覧ください。
※2011/12/20追記:秀和システムさんにも連絡して公式の正誤表となりました。

  • P.43 中段3行目:「メソッドf()」→「メソッドf」
余計な()が含まれていました。()は不要です。
柴田芳樹さんありがとうございました。

  • P.69 8行目:「2バイトずつ読み取っている」→「3バイトずつ読み取っている」
これに関しては、内部の文字コードがUTF-8なので、全角文字は基本的に3バイトとなります。JIS X0213のBMPセットからはみ出す文字は4バイトとなります。
私の文字コードの知識不足でした。
@titoi2さんありがとうございました。
  • P.108 4行目:「インターフェイスの型の変数に値を代入した後、本来の型に戻すことはできません。」→「できます」
詳細は、別の記事に残しましたのでご確認下さい。
柴田芳樹さんありがとうございました。

  • P.125 new関数の間違った使い方の例が間違っている。
詳細は、別の記事に残しましたのでご確認下さい。
柴田芳樹さんありがとうございました。

  • P.216 「今回のプログラムは、ローカルサーバで実行しようとしても、図4-19のようにエラーになってしまうので」→「図4-26」
指定している図の番号が間違っていました。正しくは図4-26です。
また、ローカルサーバでもCross Group Transactionの実行は可能です。
ただし、ローカルサーバの起動オプションの--high_replicationを指定する必要があります。
現時点では、--high_replicationはデフォルトfalseなので、Master-Slave型で動作します。

  • P.228 ユーザ認証のポイント2点目「OpenIDについては現時点ではAPIのみ提供していて動作しない」→「OpenIDはクラウド環境でFederated Loginの設定にすれば、動作する」
これは、直前で設定の手順だけ記述しましたが、(今、思えば、キャプチャ画像ぐらいは貼れば良かった)本番環境にデプロイして実行すれば動作します。
結果は、デプロイして出力結果を確認してみてください。
  • P.271 ソースコード1行目「var body = make([]byte, res.ContentLength)」→「var body make([]byte, 0, res.ContentLength)」
SDK 1.5.5ではこのままでも大丈夫だと思うのですが、1.6.1で利用する場合は先頭に余計なデータが詰まってしまうので長さ0の容量がデータ長のバッファを確保する必要があります。
別の記事にもまとめてあるのでご確認下さい。
http://takashi-yokoyama.blogspot.com/2012/01/bytesnewbuffer.html
  • P.349 「必ずデータを登録した状態で実行してください」
  • P.352 「また、最初に注意しましたが…プログラムが応答を返さなくなってしまう」→「Load()でdatastore.LoadStruct()、Save()でdatastore.SaveStruct()を呼び出すか、close(c)を呼び出してChannelをクローズしないとプログラムが応答を返さなくなってしまう」
文章自体は正しいのですが、PropertyLoadSaverのSaveメソッド(P.350(4))で、SaveStruct()かclose(c)を実行しないと登録処理を行うときにロック(応答を返さなくなる)してしまいます。
逆にP.350のLoad()メソッド(2)内でLoadStructを呼び出すかclose(c)を呼び出さないと読み出し時もロックします。
  • P.359 2段目、3行目最後「本書の内容も動作するような」→「本書の内容が動作しなくなるような」
正反対の記述になっていました。バージョンが上がると、書籍のソースコードがコンパイルエラーになってしまう可能性があります。



2011年12月8日木曜日

Googleの周辺技術(メモ)

shin1ogawaさんが発表された時の資料で、中国GTUGでの発表のネタになるかと
思ったので、ブックマークしようかと思ったのですが、
ブログに残しておこうかなと思います。

ひと通りのGoogleのAPIやサービスを知るには良い資料だと思いました。

2011年12月7日水曜日

第1回岡山PHP勉強会に参加しました。

第1回岡山PHP勉強会に参加してきたので、そのメモを残しておきます。

システム構築事例の話(…?)

  • 突発的なアクセスの増加
  • Yahooアタック
    • Yahooのトピックスにリンクが付くと…
    • 動画への直接リンクはやばい
  • PHPを選んだ理由
    • 簡単
    • みんな使っている
    • 自由度が高い
    • サーバ設定が簡単
    • 速い(?)
  • しかし
    • コードの統一性がない
    • セキュリティが最悪
  • フレームワークを活用することにした。
    • 開発時間の大幅短縮
    • ルールに従うと、コードが統一
    • DBとの連携が簡単
    • 表示が速い(ページキャッシュ機能)
  • PHP勉強法
    • 参考までに。
      • 目標を作る(アプリを1週間で作る。必ず日程を決めておく事。)
      • 入門書とリファレンスブックを購入
        • 作りたいものに近いサンプルがある本が良い
      • 説明を見ながらとにかく作る
      • リファレンスブックを見ながらソースコードを読む
      • 自作アプリケーションを作成する。
    • オープンソースを解読(バグ情報は便利)
    • 参加する
    • オープンソースを作る
    • 勉強会に参加する
  • TIPS
    • コードのガイドラインを決める
    • コードの最適化
    • セキュリティに気を使え!
      • サニタイズ処理だらけの関数等を通して無効化する。
    • 英語ができたほうが良い
    • 最新情報を得る(セキュリティ等)
    • 初級者こそフレームワークを使うべき
  • 3カ月以前の自分のソースコードを恥ずかしく思える様になること。
    • 常に精進しつづけましょう!
  • アイデアをお待ちしております!
  • 苦労した点
    • ロードバランサ
PHPフレームワーク入門
  • 無害化する方法(フレームワークを使わない場合)
    • htmlspecialchars()
    • mysql_real_escape_string()
  • いつも同じようなコードを書いている?
  • 以下のようなコードは…
    • ロジックとデザインがごちゃまぜになったコード
    • ルールが統一されていない
  • サーバを移したら動かなくなった。(PHPの場合)
    • バージョンの違い
    • 設定値の違い
    • ライブラリの不足
  • セキュリティが不安
    • いろいろな攻撃

  • フレームワーク(Framework)
    • 骨組み
    • 土台となるもの
    • 主な役割
      • 標準的な機能の提供
        • ライブラリ
        • ヘルパー関数
          • CakePHPのpr()
            • print_r()の結果を<pre></pre>で囲って出力する
      • MVCモデルの実現
        • Model
        • View
        • Controller
      • MVCモデルのメリット
        • 独立性の確保
          • 機能毎の役割が明確になる
        • 依存性の抑制
        • 保守性の向上
      • ORマッピング
      • ルールの制定
        • 命名規則
          • 変数名、テーブル名
          • ディレクトリ構成
          • コーディングスタイル
    • フレームワークのデメリット
      • 学習コスト
      • どれが良いかわからない
        • 色々なフレームワーク
          • 場合に応じて使い分ける
        • 選定基準
          • 実用性
            • 安定性
            • 機能、対応バージョン
          • 開発の継続性
          • ライセンス
          • 情報の入手しやすさ
    • CodeIgniter
      • 高速
      • 軽量
        • ソースの容量は(展開後で)1.2M
      • 低い学習コスト
      • 日本語のユーザガイドが完備
    • CodeIgniterのURL
      • index.phpがフロントコントローラ
        • URLは、index.php/fuga/piyo/paramなど。
          • class fuga extends CI_Controller {
            • function piyo($param) 
    • 便利な機能
      • active_record
      • form_validation
    • View
      • 共通部分はinclude

セキュリティについて考えてみよう
  • バグ、脆弱性
    • バグとは何か?
      • なるべきものが、そうならない。
    • 脆弱性とは何か?
      • バグと言えばバグ。
      • そのうち、セキュリティに関係するもの
        • 例)脆弱なOSで動作しているサーバがあっても、ファイアウォールで完全に隔離されていれば問題はない。
          • 外部から接続できないので。
      • セキュリティホール、脆弱性はバグの一部。
    • アプリケーションが正常に動作するように作ること。
      • 「一定の定義」に従って正常に動作するのであれば問題ない。
    • リスクを知り、対応する
      • 以下のような問題に対して
        • SQL Injectionでデータを取られた
        • SQL Injectionでページを書き換えられた
      • Webアプリケーションは「最もリスクがあるもの」
        • 全世界に向けて公開する前提だと。
        • 自分のサーバは人気がないから問題ないだろう。
          • クラックする人は、踏み台にするためにサイトの大小に関わらず攻撃してくる!
          • 従って、これは間違い。
    • リスクとは何か?
      • CVEというデータベースがある。
    • 入力、処理、出力
      • エコーバック問題?
      • 9割方、入力と出力の部分で対処がない。
      • 基本的に自分のアプリ以外は全て信用できない前提で考える。
        • 信頼境界線
      • 入力は「全てバリデーション」
        • 「サニタイズ」とは違う
          • ブラックリスト的考え方。(悪いものを弾く)
          • validationはホワイトリスト的考え方。(良いもののみを受け入れる)
      • 処理は「ベストプラクティスに従う」
        • 話をすると長くなるので省略
        • めんどくさい
      • 出力
        • エスケープを理解し、エスケープする
        • ヘルパーを理解し、ヘルパーを使う
          • 属性名をエスケープしないヘルパーがあるので、下手すると、そこがXSSの原因になる可能性も。
        • エスケープもヘルパーも使えないものはバリデーション
        • どうしようもないもの、絶対に安全だとわかっているもの
          • そのまま出力
    • アプリケーションが正しく動作することを担保する
      • 特にセキュリティに特化する場合
        • CIAを保証する
          • Confidential(機密性)
          • Integrity(統合性)
          • Availability(可用性)
      • セキュリティ対策に役立たないセキュリティ対策はない
    • セキュリティ対策とはリスクマネジメント
      • リスクを許容できれば、どんな対策でも構わない。
        • リスクを理解した上で、どこまでリスクを許容できるのか。
        • ただし、他人に迷惑はかけない
      • 例えば、文字エンコーディングのバリデーション
        • 入力時に文字エンコーディングをバリデーションする。
      • 適切な設計も必要
      • どれが優れたセキュリティ対策か?よりも、必要なセキュリティ対策か?が重要



2011年12月3日土曜日

第11回中国GTUG勉強会

第11回勉強会を開催しました。内容のメモを残しておきます。

DevQuizへの参加

  • Googleの開発者向けイベント
    • できるだけ能力の高い人に参加してもらうため
    • より多くの開発者に参加してもらう
    • 公平な選抜方式
    • イベントの前に開発者に楽しんでもらう
  • ウォームアップ問題
    • Google技術のトリビア
  • 分野別問題
    • Web Game
      • JavaScriptを使った神経衰弱
    • Go
      • PNG画像を与えられて、何色の画像があるかを調べる
    • Android
      • AIDLを使ってデータを抜き出す。
    • Google Apps Script
    • 一人ゲーム
  • スライドパズル

  • 参加者:3000人
  • 通過者:1000人
  • ボーダー:100.56点/150点
  • スライドパズルは、結果を探索するコードをバグ無くかければ。。
  • スコア分布
    • 100〜110点のところに大半の方が分布
  • 問題作成チームのコメント
    • みんな頑張りすぎ。
    • 30人も満点を取るとは思っていなかった。

  • スライドパズル
    • 解決するための定石
    • 幅優先探索
      • 1手後、2手後の状態を保持して、ゴールの状態になるかを調べる
    • 双方向探索
      • スタートとゴールから幅優先探索
    • でも、最短経路を見つけるのは無理!という結論
      • 20Byteぐらい保持して、2億通りなので、4GBぐらいになる。PCではこれが限界。
      • ゴールに近づいたかどうかを評価する関数を準備。
        • 当然、壁の有無も考慮しなければならない。
        • この時点で844問/5000問
    • 評価関数に一工夫をする。
      • 先に盤面の真ん中を揃えると、左上を揃えに行く時に乱される。
        • 無駄が多くなる。
      • 人間だと左上から揃えるようにする。
        • 人間が解決する方法を考えると解決策が思いつく場合がある。
    • メモリの省力化
      • 経路を1byte保持→2bit保持へ。
      • intをint8_tへ。
      • 4000問ぐらいまでは結構行ける。
    • 難しいケースの対策
      • 通路のようになっているケース
      • 4966問/5000問
    • もっと難しいケース
      • 結局、手動で解いた。
      • 5000問/5000問
    • 手数は12426手余った。
    • 最長手数は303手
    • 思考・コーディングは40時間
    • 計算時間は40時間
    • 最後の手動の問題を解くのに10時間位
  • 言語はC++で。
    • 処理速度が重要
    • 寝るときに計算し始めて…
      • 起きた時に終わる or 丸一日
    • C++11は便利
      • 拡張for
      • 型推論のauto
      • ラムダ式
      • サイズを指定できる整数型
    • 実装上のほそぼそとしたこと。
      • 盤面サイズをテンプレートパラメータ化
        • 1.5倍ぐらいの速度向上
        • ただし、コンパイル時間は16倍…
  • Samurai Coding
  • TopCoder
  • Code VS
  • AI Challenge Ants(スポンサーがGoogle)

  • 近似解を求めるプログラムの重要性
    • 「アルゴリズムイントロダクション」の練習問題より。

  • NASA TopCoder Challenge
    • NASAがスポンサー
  • 身につく能力
    • ボトルネック以外を最適化する無意味さ
      • 面白いぐらい無意味なんだそうです。手を付けやすい所からやってしまうという人間の性も。
    • 実装の難しさと効果を天秤に掛ける感覚
    • コードを綺麗に保つことの大事さ
      • 後で改造が難しくなる
    • 作業管理
      • バージョン管理は大事!

  • EXP-Hackathon
    • WebIntents、GITKitを使って簡易画像ピッカー
    • 自動飲み会幹事システム
    • Hangoutsを自分のガジェットに埋め込む
    • etc

Google Code Jam Japanに参加した
  • TopCoderは言語の縛りがあるが、Google Code Jamについては、縛りはない。
    • TopCoderはAppletか何かで動作しなければNGとなるかも?
  • Google Code Jam Japan
    • 問題は3〜6問
      • SmallとLarge
        • Smallは制限時間4分(再挑戦可能、即答される)
        • Largeは制限時間8分(時間内に限り、再挑戦可能)
    • テストケースの入ったファイルをダウンロードし、実行結果をソースコードと一緒に提出
    • 各問題の得点と回答した時間で順位が付く
  • 競技の流れ
    • 参加登録(2月中旬登録開始)予選終了前なら登録可能
    • 練習問題
    • 予選(10/1 13:00〜19:00)
      • 6時間で3問の問題
        • 予選で1問以上の問題でSmall、Largeの両方を解いた人のみ
        • 600人程度
    • 決勝(10/8 13:00〜16:00)
      • 3時間で5問の問題
  • 戦略
    • 言語:Java(Eclipse)
    • 予めプロジェクトを作成しておく
      • ファイルを読み込み、出力するというテンプレート的なコード等
    • 先に問題を全部読んで、解けそうなものから解く
    • サンプルの入力・結果で確認
      • 問題にサンプルの入力、結果がある。
  • 予選
    • B問題はコーヒーの幸福度、賞味期限を扱う
    • C問題はビット数を数える
  • 決勝
    • 手も足も出ず
    • 長さを持つアンテナのエレメントを並べて、感度が良くなるパターンを算出。みたいな問題など
Google Developer Day 2011のフィードバック
  • 技術的な情報を紹介するイベント
  • OAuth1.0→OAuth2.0へ!
  • OAuth2.0とOpenID Connectによる認証
    • Google Identity Toolkit
    • Account Chooser
  • Google APIs Consoleで登録
  • OAuth2.0のaccess_tokenを取得
    • Scope https://www.googleapis.com/auth/userinfo.mailなどを指定。
  • Account Chooser
    • https://account-chooser.appspot.com
    • 認証で使うウィジェット
  • 認証はGoogleなどのクラウド側に任せてしまって、アプリケーションの開発に力を注いだほうがいいのでは?
  • Chromeのデベロッパーツールについて
    • HTML/CSSの編集・更新、差分履歴、バージョン管理
    • スタイルシートの変更をリアルタイムに反映
    • 定義を追加も可能
    • 補完機能
    • 差分履歴、バージョン管理
      • 変更履歴が残る
      • 指定するバージョンに戻すことも可能
    • Firebug CommandLine APIとの互換もある。
    • リモートデバッグ

  • HTML5のオフライン機能
    • バイナリデータの保存
      • File System API
と、言う感じで、タイムアップ
資料は、公開されたら中国GTUGのサイトで公開します。