Go言語でのテストの並列化 〜t.Parallel()メソッドを理解する〜 [golang]
2020-08-24 08:26
コメント(0)
bytes.Bufferの実装の変更 [golang]
プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- 作者: Alan A.A. Donovan
- 出版社/メーカー: 丸善出版
- 発売日: 2016/06/20
- メディア: 単行本(ソフトカバー)
『プログラミング言語Go』の「6.6 カプセル化」で
bytes.Buffer
に関して次のような記述があります(193ページ)。例として、実際に、Go 1.11まではこの記述にあるような実装なのですが、次のGo 1.12ではこのbytes.Buffer
型を考えてみてください。 この型は非常に短い文字列を蓄積するために頻繁に使われます。したがって、そのようによくある場面でのメモリ割り当てを避けるために、そのオブジェクト内に少し余分な領域を確保するのは有益な最適化です。Bufferは構造体型なので、その領域は大文字で始まっていない名前を持つ [64]byte
型の追加のフィールドの形式になります。このフィールドが追加されたとき、それは公開されなかったので、Buffer
を使うbytes
パッケージの外部のクライアントは、改善された性能を除いたどの変更にも気づきませんでした。
[64]byte
型の追加のフィールドは削除されるようです。修正のコミットは、こちらです。2018-09-15 17:55
コメント(0)
『Java Puzzlers』とGo言語(2) [golang]
パズル3: 長除法(Long Division)このプログラムの実行結果は、
このパズルは、2 つのlong
値を割るプログラムに関することなので、LongDivision と呼ばれます。被除数は一日が何マイクロ秒であるかを表し、除数は一日が何ミリ秒であるかを表しています。このプログラムは、何を表示しますか?
public class LongDivision { public static void main(String[] args) { final long MICROS_PER_DAY = 24 * 60 * 60 * 1000 * 1000; final long MILLIS_PER_DAY = 24 * 60 * 60 * 1000; System.out.println(MICROS_PER_DAY / MILLIS_PER_DAY); } }
5
です。その理由は、Javaではint
型(上記の数値リテラルはすべてint
)から構成される式の演算結果の型はint
なので、上記のMICROS_PER_DAY
への代入の右辺の式の計算結果はint
に収まらずにオーバーフローが発生しているからです。その結果、小さな値となっており、実行結果が5
なのです。単純にGo言語で書いたコードは次のようになります(対比しやすいように、Go言語の命名規則には従っていません)。
このコードの実行結果は、package main import "fmt" func main() { var MICROS_PER_DAY int64 = 24 * 60 * 60 * 1000 * 1000 var MILLIS_PER_DAY int64 = 24 * 60 * 60 * 1000 fmt.Println(MICROS_PER_DAY / MILLIS_PER_DAY) }
1000
です。その理由は、右辺の式に書かれているものはすべて定数つまり「型付けなし整数」であるため、式の演算はコンパイル時に計算されます。そして、その計算結果の値も「型付けなし整数」なのです。「型付けなし整数」の値は、型がある変数(上記の場合、
int64
のMICROS_PER_DAY
)への代入において、変数の型(int64
)の取り得る値の範囲に収まれば、コンパイルされます。収まらなければ、コンパイルエラーです。2017-11-29 06:56
コメント(0)
『Java Puzzlers』とGo言語(1) [golang]
先週の金曜日のGo言語研修が終わって、懇親会(会社の食堂)まで時間があったので、『Java Puzzlers』をやってみました。
もう12年前の本で、現在は絶版となっています。発売された時に、日本でJavaOneが開催されていて、印刷されたばかりのこの本が販売された頃が懐かしいです。
ところで、Javaではパズルになるものが、Go言語ではそもそもコンパイルエラーになるものが多いです。その理由の一つは、異なる整数型の混合計算をGo言語が許さないことです。初めてGo言語に触れると、その点がちょっと煩わしく感じます。でも、パズルをGo言語で書くとどうなるかを知ると、言語の違いが分かってきて面白いです。
Go言語で同じコードを書くと次のようになります。
それは、
もちろん、定数ではない
型付けなし定数については、『プログラミング言語Go』の「3.6.2 型付けなし定数」(p.87)でも説明されていますが、上記の丸めについては書かれていません。
もう12年前の本で、現在は絶版となっています。発売された時に、日本でJavaOneが開催されていて、印刷されたばかりのこの本が販売された頃が懐かしいです。
ところで、Javaではパズルになるものが、Go言語ではそもそもコンパイルエラーになるものが多いです。その理由の一つは、異なる整数型の混合計算をGo言語が許さないことです。初めてGo言語に触れると、その点がちょっと煩わしく感じます。でも、パズルをGo言語で書くとどうなるかを知ると、言語の違いが分かってきて面白いです。
パズル2: 変革の時(Time for a Change)これを実行すると結果は、
次の文章問題を考えてみてください。
トムは、$1.10 するスパークプラグを購入するために自動車部品店に行きますが、財布の中にあるのは2 ドル紙幣ばかりです。2 ドル紙幣でスパークプラグの代金を支払ったとしたら、彼は、お釣りをいくら貰うでしょうか。
この文章問題を解こうとしているのが、次のプログラムです。このプログラムは、何を表示しますか?
public class Change { public static void main(String args[]) { System.out.println(2.00 - 1.10); } }
0.8999999999999999
となります。その理由は、1.10
を浮動小数点数では正確に表現できないからです。Go言語で同じコードを書くと次のようになります。
そして、実行結果は、package main import "fmt" func main() { fmt.Println(2.00 - 1.10) }
0.9
です。なぜ、Go言語でこうなってしまうのでしょうか?それは、
2.00
や1.10
の扱いの違いです。Go言語では、それらは「型付けなし(untyped)浮動小数点数」です。そして、Println
の引数の式は定数リテラルの演算なので、コンパイル時に定数として計算されます。この定数計算に関しては、Go言語では言語仕様ですべのGo言語の実装に対して、次のように高い精度を要求しています。Represent floating-point constants, including the parts of a complex constant, with a mantissa of at least 256 bits and a signed binary exponent of at least 16 bits.しかし、いくら高い精度でもっても、正確には表現できないはずです。そこで、言語仕様では次の条件が付加されています。
Round to the nearest representable constant if unable to represent a floating-point or complex constant due to limits on precision.つまり、定数計算の結果は、表現可能な最も近い値の定数となるのです。
もちろん、定数ではない
float64
の変数に代入してから計算すると、0.9
にはなりません。このコードの実行結果は、package main import "fmt" func main() { var x, y float64 = 2.00, 1.10 fmt.Println(x - y) }
0.8999999999999999
です。型付けなし定数については、『プログラミング言語Go』の「3.6.2 型付けなし定数」(p.87)でも説明されていますが、上記の丸めについては書かれていません。
プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- 作者: Alan A.A. Donovan
- 出版社/メーカー: 丸善出版
- 発売日: 2016/06/20
- メディア: 単行本(ソフトカバー)
2017-11-28 08:24
コメント(0)
内容補足:『プログラミング言語Go』 [golang]
プログラミング言語Go (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- 作者: Alan A.A. Donovan
- 出版社/メーカー: 丸善出版
- 発売日: 2016/06/20
- メディア: 単行本(ソフトカバー)
すでに本になってしまったので訳注を追加することはできませんが、補足として書いておきたいと思います。
7.8節「
error
インタフェース」(p.226)に次の記述があります。error を作成する最も簡単な方法は、指定されたエラーメッセージに関する新たなerror を返す errors.New を呼び出すことです。errors パッケージ全体は、次の4 行しかありません。文字列は不変(immutable)なのですが、リフレクションを使用すると書き直すことができます。リフレクションを使用して文字列を書き直したコード例はこちらです。package errors func New(text string) error { return &errorString{text} } type errorString struct { text string } func (e *errorString) Error() string { return e.text }errorStringの基底型は、その表現を不注意な(あるいは意図的な)更新から保護するために、文字列ではなく構造体です。(以下省略)
一方、構造体の非公開なフィールドはリフレクションを使用して書き換えることはできません。そのことは、p.396に記述されています。
Display をos.Stdout へ適用した場合、Unix ライクなプラットフォーム上のos.File 構造体のfd int フィールドといった、通常の言語規則に従えばアクセスできない構造体の非公開なフィールドの値をリフレクションが読み出せることが分かります。しかし、リフレクションでそのような値を変更することはできません。
(コード例は省略)
アドレス化可能なreflect.Value は、走査によって構造体の非公開のフィールドが得られたかどうかを記録しており、そうであれば変更を許しません。
『プログラミング言語Go』刊行記念トークセッション [golang]
7月6日(水)に開催されるGoogleのソフトウェアエンジニアである鵜飼文敏氏とのトークセッションです。鵜飼文敏氏からは、書籍の帯のメッセージをいただきました。鵜飼氏は、次の本の監訳をされていますし、『Binary Hacks ―ハッカー秘伝のテクニック100選』を共著で執筆されています。
無料ではなく入場料はドリンク付きで1000円ですが、奮ってご参加ください。ジュンク堂のイベントページは、こちらです(事前予約が必要です)。
当日は、著者アラン・ドノバンとブライアン・カーニハンのサインが書かれた日本語版が展示される予定です。
第1章公開:『プログラミング言語Go』 [golang]
発売に先行して、以下の内容を含むPDFが公開されました。PDFはこちらです。
- 日本語版によせて
- 目次
- まえがき
- 第1章 チュートリアル
『プログラミング言語Go』刊行記念イベント [golang]
池袋のジュンク堂で「Goの設計思想を読み解く~実際の開発に活かすために」と題して、刊行記念イベントが開催されます。鵜飼さんとのトークイベントです。
開催日時:2016年07月06日(水) ~事前予約が必要ですので、参加方法などの詳しい情報はこちらを見てください。
場所:ジュンク堂 池袋本店
鵜飼 文敏(Googleソフトウェアエンジニア)
柴田 芳樹(『プログラミング言語Go』訳者)
19:00開場
19:30開演
Go言語に関する日本語書籍 [golang]
これから出る本も含めてGo言語に関する日本語の書籍を列挙してみました。今年は6月までに4冊であり、Go言語の普及を後押しすると思います。
【2016年】
【2015年】
【2012年】
【2011年】Go言語プログラミング入門on Google App Engine
- 作者: 横山 隆司
- 出版社/メーカー: 秀和システム
- 発売日: 2011/12/14
- メディア: 単行本
【2010年】