ラベル 正誤表 の投稿を表示しています。 すべての投稿を表示
ラベル 正誤表 の投稿を表示しています。 すべての投稿を表示

2012年1月14日土曜日

Go言語プログラミング入門の正誤表を更新しました。

Go言語プログラミング入門正誤表に追記しました。
http://takashi-yokoyama.blogspot.com/2011/12/go.html

appengine/datastoreパッケージのPropertyLoadSaverについて、
誤記があったので、詳細に説明をしておきたいと思います。

PropertyLoadSaverインターフェイスのドキュメントです。
http://code.google.com/intl/ja/appengine/docs/go/datastore/reference.html

書籍では、「データを登録した状態でないとプログラムが応答を返さなくなる」という
事が書かれているのですが、これは、サンプルコードを作成している時の試行錯誤の
途中段階の誤認識をした状態で記述をしていました。

実は、PropertyLoadSaverインターフェイスのLoadメソッド、Saveメソッドの定義は
以下の通りです。(書籍のサンプルコードから抜粋したものです)
func (g *Guest) Load(c <-chan datastore.Property) os.Error {
func (g *Guest) Save(c chan<- datastore.Property) os.Error {
どちらもchannelが引数になっています。このchannelについての説明はP.63付近に
少し記述をしていますが、CriticalSectionと同じで、自分のスレッドをブロックします。
ブロックが解除されるのはchannelに値がセットされた時か、close(c)された時と
なります。LoadStruct()、SaveStruct()はメソッド内でchannelの処理を行っているため、呼び出せば構造体に値がセットされ、channelの処理も適切に行ってくれます。

書籍のプログラムだと、Saveメソッドの方では、何もしていないため、channelのブロックが解除されないことになり、現時点ではプログラムが応答を返さなくなってしまいます。

したがって、Load()の方でも、同様に「何もすることがない」からといって何もしないと
プログラムが応答を返さなくなってしまいます。

2012年1月2日月曜日

bytes.NewBufferの使い方

Go言語プログラミング入門でもURLFetchAPIを利用した例で出てきたのですが、
掲載しているソースコードだとあまり良くないので再度使い方をまとめておきます。

import "bytes"

var writedata = make([]byte, 0, length)
var writebuf = bytes.NewBuffer(writedata)

書籍では、make([]byte, length)を使っていますが、この意味は、"長さと容量がlengthのバッファ"が作成されます。

bytes.NewBufferを利用する場合は、長さは0で、容量が必要なサイズに設定されている事が望ましいとされています。

したがって、"長さは0"というのを明示するために上記の例にしなければいけません。

実際に、GAE/G SDK 1.6.1で実行してみると、0埋めされたデータが出力されていました。
Buffer.Write([]byte)は容量が足りない場合は、バッファの容量を増やしてくれるように
なっているので、var writedata = make([]byte, 0)でも良いかもしれません。
この場合、容量が0なので、容量を内部的に増やす処理(新しいバッファを確保して上書きコピー)が実行されるため
実行コストが増えてしまいます。

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月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年7月29日金曜日

Google Android WebAPIプログラミング入門(正誤表)

私が執筆したGoogle Android WebAPIプログラミング入門の正誤表を載せておきたいと思います。(ちなみに以下の本です)
このページは非公式のものとします。(2011/12/20:秀和システムさんに連絡して公式の正誤表となりました。)
また、発見、報告があり次第、追記したいと思います。



正誤表
P.272−9行目:
(誤)また、後述しますが最新版Twitter4j 2.2.1が…
(正)また、最新版Twitter4jが…

9章の9-4に関して書籍のサンプルが動作しなかったという報告をいただきました。
ありがとうございます。現象を確認したいのですが、すぐに時間が取れないので、
取り急ぎ、サイトへのリンクを掲載しておきます。
http://sarl-tokyo.com/wiki/index.php?Google%20Android%20WebAPI%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%85%A5%E9%96%80%E3%82%92%E8%AA%AD%E3%82%93%E3%81%A7%E3%81%84%E3%81%A6