タグ

ブックマーク / qiita.com/ruiu (6)

  • Goでスレッド(goroutine)セーフなプログラムを書くために必ず注意しなければいけない点 - Qiita

    Goは言語機能として並列実行をサポートしているけど、Goで書いたからといって自動的にデータ構造がスレッドセーフになるわけではないので、スレッド安全性を気にしなければならないはこれまでの言語と変わらない。どういうケースが良くてどういうケースがダメなのかを理解していないと安全なプログラムは書けない。それについて説明をしよう。 まず第一にEffective Goのこの一文は覚えておこう。 Do not communicate by sharing memory; instead, share memory by communicating. メモリを共有することで通信しようとしないこと。代わりに通信することでメモリを共有すること。 変数の値を変更したあとにチャネルなどを使わずに、おもむろに別のgoroutineからその変数の値を読み書きしてはいけない。そういうやり方だと読み書き操作の前後関係がき

    Goでスレッド(goroutine)セーフなプログラムを書くために必ず注意しなければいけない点 - Qiita
  • 作りたいものを作るには結局大量のコードを書かないといけないことについて - Qiita

    Register as a new user and use Qiita more conveniently You get articles that match your needsYou can efficiently read back useful informationYou can use dark themeWhat you can do with signing up

    作りたいものを作るには結局大量のコードを書かないといけないことについて - Qiita
  • GoでNewなんとかのような関数を不必要に提供しないほうが良い理由 - Qiita

    構造体を定義して、それに対してメソッドを定義して、最後にその構造体をアロケートして初期化するNewなんとかという関数を用意する、というのを何の疑問も持たずに行っているならちょっと考えものだ。途中まではよいが、Newなんとかみたいなのは別に必須ではない。 メソッドとゼロ値 Goでは新しい値は「ゼロ値」で自動的に初期化される。ゼロ値は型ごとに違うが、数値なら0、文字列なら空文字列、ポインタやインターフェイスならnil、といった具合の値だ。構造体ならそれぞれのフィールドがゼロ値で初期化される。 メソッドはそのレシーバーの値のゼロ値に対して問題なく動くように書くほうがよい。構造体Tを割り当てて初期化する関数としてNewTみたいな関数を用意するのは、当に初期化が必要なとき以外はやらないほうがよい。 なぜか、というといくつか理由がある。 NewTの代わりにnew(T)を使うようにすると、エクスポート

    GoでNewなんとかのような関数を不必要に提供しないほうが良い理由 - Qiita
  • panicはともかくrecoverに使いどころはほとんどない - Qiita

    Goを書いていてrecoverを使うことはまずほとんどない。頻繁にrecoverを書いているとしたらなにかが間違っているのでプログラミングスタイルを見直すこと。 Goでのエラーハンドリング Effective Goなどで説明されているように、Goではエラーは関数の返り値として返される。たとえばio.ReaderのRead関数は、読み込んだバイト数と、(nilかもしれない)エラーの2つの値を返す。Goでは基的に、エラーは常にこういう通常の値としてハンドルするべきで、エラーの時のための特別な制御構造(try 〜 catch)のようなものを使うのは、利点より害のほうが多いという考え方をとっている。 (同じような考えで例外を使用禁止にしている大規模C++プログラムはいくつもある。たとえばChromiumなどはそうだ。LLVM/Clangもパフォーマンス上の問題で例外を使っていない。C++コンパイ

    panicはともかくrecoverに使いどころはほとんどない - Qiita
  • Goにatexitやグローバルなデストラクタがない理由 - Qiita

    CやC++ではatexit関数で関数を登録しておくと、プログラムの終了時にその関数を自動的に走らせることができる。そういう機能はRubyPythonにもある。 Goにはそういう機能はない。実装を忘れているのではなくて、意図的にそういう機能を持たせていないのだ。これについてIan Lance Taylorさんが大変説得力のある説明をしていた。 まず第一に、どんなプログラムでも任意の箇所でクラッシュしうるし、まったくバグのないプログラムでもいきなりkillで殺されたりマシンが電源断で落ちるということがある。従ってどんなプログラムも、突然終了させられたあとに、もう一度きちんと動くことができなければならない。つまりatexitはきれいに終了するための機能ということで、atexitが呼び出されないとうまく動かないプログラムというのはそもそも間違っているということになる。 大きなC++プログラムでは

    Goにatexitやグローバルなデストラクタがない理由 - Qiita
  • Goでxxxのポインタを取っているプログラムはだいたい全部間違っている - Qiita

    Goで、文字列、インターフェイス、チャネル、マップ、スライスのポインタを取っているプログラムは、書いた人がきちんと自分がなにをしているのか理解しているのでなければ、ほぼ確実に間違っているといっていい。 Goではある種の型の値はそもそもポインタのようなものである。上記の型はどれも任意の大きさになり得るが、大きくなりうる実体のデータはヒープに確保されていて、値そのものが持っているのはそのヒープ上への値へのただのポインタ+多少の付随的なデータにすぎない。こういった値を値渡しではなくポインタ渡しする必要はない。ポインタのデリファレンスのほうがポインタのコピーより高くつくし、余計な混乱を引き起こすだけだからだ。もしこういう値をポインタ渡ししているとしたら、そのコードはなにか深い意味があるのではなく、それを書いた人が大きな値がコピーされると勘違いしていて書いた可能性のほうがずっと高い。 文字列は2ワ

    Goでxxxのポインタを取っているプログラムはだいたい全部間違っている - Qiita
  • 1