Go language part 5

■ このスレッドは過去ログ倉庫に格納されています
2022/02/27(日) 07:43:20.04ID:uWHjNeVw
Goについて扱うスレッドです。
GoはGoogleによって開発された言語です。

公式
https://golang.org

公式ドキュメント
https://golang.org/doc/

公式外パッケージドキュメント
https://godoc.org

ブラウザ上で試し書き
https://play.golang.org


※前スレ
Go language part 4
https://mevius.5ch.net/test/read.cgi/tech/1605467680/
2022/09/01(木) 12:50:03.20ID:cWwvmbGP
この辺の問題が起きないようにしっかり対策取ってる?
https://www.uber.com/blog/data-race-patterns-in-go/
https://blog.acolyer.org/2019/05/17/understanding-real-world-concurrency-bugs-in-go/
2022/09/01(木) 12:54:11.77ID:dbQKPphW
複合リテラルとして書けばいいんだし、落とし穴的な問題はなくない?
俺は悪くないかなと思ってるんだけど
2022/09/01(木) 13:00:51.78ID:dbQKPphW
>>520
「これらの多くは、チャネルでの送信または受信の欠落、またはチャネルの閉鎖が原因です」
いや、mallocしといてfreeしてませんでしたレベルの話をされてもどうしろと?
普通に対策考えないでプログラミングなんてできないだろ
2022/09/01(木) 14:02:59.57ID:dbQKPphW
>>518
ポインタを示す型なら&を使ってT &pにしてデリファレンスは*p
とか実際に書いてみたら物凄い違和感に襲われてしまった

…C言語の呪いって凄いわ
2022/09/01(木) 14:17:02.40ID:3zc//kWQ
>>522
それってプログラマー任せのノーガード戦法ってことでしょ?
リストアップされてるような各種バグに対してシステマティックに検知・防止する仕組みを実装できてる?
2022/09/01(木) 17:08:27.97ID:V2mDAtzH
データ競合はあまり遭遇したことないな
無駄に並列化したがるバカがチームにいると地獄を見るだろうというのはわかる
channel絡みのミスで固まるのはよくある
2022/09/01(木) 18:05:50.03ID:Wlby5VAy
>>522
けっこう終了時の後処理とか難しくない?
適当なツールとかだと雑に済ましちゃうし、割ときちんとやろうとすると書けない人多い印象。
2022/09/01(木) 18:16:08.12ID:0As8hqIp
きつい現場のGoは他の言語より殊更きつそうだというのはわかるわ
2022/09/02(金) 02:30:51.60ID:bNDG9t//
channelは複雑なデータのやり取りに使うには難しすぎると感じるね
どこで詰まるかわかったもんじゃないし
公式がまともなフレームワーク用意するわけでもないし
2022/09/02(金) 03:08:08.96ID:xpSIPhaW
epollを使うよりかはマシだし
2022/09/02(金) 08:58:55.58ID:0WCZpZUS
いや、Goに限らない問題でGoのダメなところとか言われてもなぁ
2022/09/02(金) 09:55:02.48ID:zLWkNNSX
いや、けっこうGoに限った問題
channelのユースケースの大部分は現実にはpromise/futureで十分で、遥かにミスを引き起こしにくい
2022/09/02(金) 09:58:48.22ID:0WCZpZUS
例えばCとかでファイルを排他オープンしたままクローズし忘れて書き込みのままになってて、別の箇所で読み込もうとしたけど開けなかったとして
これはC言語の不備だとか言うのか?と
2022/09/02(金) 10:04:00.39ID:0WCZpZUS
>>531
chan のユースケースといったら、パイプとしてストリーム的にデータを流すのが主だと思うんだが、promise, future でどうやって代替するの?
2022/09/02(金) 10:06:18.95ID:0WCZpZUS
>>531
select文のあたりでも書かれてたと思うけど、同期を取る目的じゃなくてパイプからの機能だよチャネル
2022/09/02(金) 10:10:39.85ID:0WCZpZUS
>>531
同期取るなら、sync.WaitGroup 使えばよくない?
2022/09/02(金) 12:33:43.05ID:Xv0heE2X
>>532
そういうことにならないようにGoのdeferやC#のusingやPythonのwithみたいな仕組みを言語機能として提供してるよね?

それらが不要だとでも?
2022/09/02(金) 12:45:23.85ID:bNDG9t//
いや普通に同期を取る使い方もできるだろw
完了通知を待つ使い方
俺もその使い方しかしてない
async/awaitなんで構文として追加しても良いと思うのだけどね
channelは非同期機構を実装するパーツとしては優秀だから
フレームワークが欲しい
2022/09/02(金) 13:40:10.47ID:D0FuWgPr
そもそも本当にパイプとしてストリーム的にデータを流す必要のあるケースなんて稀
Goがchannel推しだから利用者もそれに引き摺られてストリームっぽい設計になりがちなだけで、結果として単一の値(又は配列)を返せれば殆どのケースでは十分
本当にストリームが必要ならJavaScriptのasync generatorのような設計も可能で、producerとconsumerが協調するからchannelより遥かに安全だ
2022/09/02(金) 13:56:23.23ID:iQ46VdDW
そもそもストリームモデルが必要なユースケースってほぼ
分散環境だと思うんだよな
2022/09/03(土) 12:27:35.16ID:62gf404N
分散環境なら外部のメッセージバスに投げるだけだよね
せっかく小さいgoroutineを気軽にポコポコ起こせるデザインなのに、
結果を受け取る方法が、データ競合を起こさないように最大限注意して共有変数を使うか、パラダイムのミスマッチなchannelを使うかなのは片手落ちに感じる
単純にgoroutineの返り値をwaitできるようにしない理由ってあるんだろうか?既に議論されてたら知りたい
2022/09/03(土) 13:39:36.59ID:Aru3Abt3
>パラダイムのミスマッチなchannel

kwsk
2022/09/03(土) 20:41:16.91ID:eoULSfLD
>>541
そりゃ>>533の通りで、channelはストリームでありfutureではない、ってことだ。
futureで済むケースにchannelを使うと、複数の値を返す可能性はないのか?1つも結果を返さなかったら?
そんな余計な心配が常に付き纏うことになる。futureなら全く無縁な心配がな。そしてその心配が現実になればプログラムは容易にデッドロックする。
2022/09/03(土) 20:49:18.55ID:CkDP1XSv
>>536
だからdeferあるんだし、ちゃんとリソース管理しろよ、という
Goのせいにするのはお門違いだろ、な?
2022/09/03(土) 20:53:14.26ID:CkDP1XSv
>>542
promise, future 程度のことをやりたきゃ、>>535で書いたけどsync.WaitGroup使ったらどうだ?
2022/09/03(土) 21:09:58.32ID:2QtFsvwZ
パラダイムのミスマッチという理由がわからん。
goroutineは一つの関数を呼ぶためのもんじゃないぞ。
goroutine立てて一連の処理を同期的に書くためのもなんよ。普通に考えれば結果を受け取る必要が無いはずだよ。
どうしても集めるならfan inするように一つのchanで受ける。

Futureは要らないんよ。awaitとかしなくてもそこでCPU占有したり、ioなりなんなりが起これば自動的に別goroutineに制御が渡る。
2022/09/03(土) 21:10:11.97ID:Aru3Abt3
>>542
ストリームだとミスマッチでfutureだとミスマッチじゃないということか?
何と何がミスマッチなのかというところがよくわからんが。
2022/09/03(土) 21:14:31.20ID:eoULSfLD
>>544
その場合は「共有変数を注意深く使う必要がある」よね
2022/09/03(土) 21:22:59.76ID:eoULSfLD
>>545
だからそう言ってるでしょ
goroutineとchannelをfutureのように使おうとすればミスマッチのために煩雑でバグの生じやすいコーディングを強いられることになる
もちろんGoにはGoのやり方があるのは分かるが、一方でその結果が>>520の状況なのが事実だよね
2022/09/03(土) 21:29:09.46ID:2QtFsvwZ
>>548
goroutineで処理すべき単位とか、ワークスティーリングの話してなかったかなと。
550デフォルトの名無しさん
垢版 |
2022/09/04(日) 00:29:35.08ID:ULs4IOBU
まさかこのスレにホーアのCSP本読んでないやついないよな?な?
2022/09/04(日) 00:54:37.91ID:6UpdVUMR
いや、読んでませんが?
2022/09/04(日) 17:28:10.39ID:GIlWqA7r
>>550
読もうとしたけどガチの論理学的数学で挫折
しかしよく調べたらGoが参考にしたのはその本ではなく
最初にホーアが出したもっと簡単な論文の方だった
つまりその本は読む意味はない(Goの並行モデルの理解という意味で)
2022/09/04(日) 18:08:07.32ID:VepAvQjQ
>>547
それは認めざるを得ない
Mutexと会わせ技で使ってるから
2022/09/04(日) 19:08:07.89ID:VepAvQjQ
>>547
だけど、120行(+テスト75行)の隠蔽ライブラリを書いて使ってる
共通変数の管理なんてその程度の共通化でカバーできるタスクじゃん
555デフォルトの名無しさん
垢版 |
2022/09/04(日) 23:01:27.23ID:ULs4IOBU
すまない誰かリングにかけろで例えてくれないか?
2022/09/05(月) 01:58:21.42ID:7mfke0+F
Goがpromise(future)/async/awaitをサポートしてくれれば今より容易に安全に書けるケースが増えるのは事実だが、
この件も他の件と同様にGoはサポートしてくれないだろうという悲観的な現実と向き合って、
今ある手段で頑張って代替手段を安全に実現しよう。
2022/09/05(月) 04:13:05.73ID:098gBdTn
結局ゴルーチンの実装が中途半端だったんだろうね
分散環境でのストリームモデルならNodeみたいなノンブロッキングIOで外部のソケットを叩けるようにして
シングルスレッドにするのが良かったし
そうでないならFuture/Promiseみたいに安全にデータを受け取れる仕組みが欲しかった
この2つがちょうどうまくできないデザインになっちゃった
2022/09/05(月) 04:31:49.54ID:098gBdTn
またGoの言語仕様にも問題があった
ジェネリクスだ
ジェネリクスがない状態でfuture/promiseを安全に実装できない
なぜかアンチジェネリクス勢がGoには多く
コミュニティでの議論も進展しなかった
つまり全てがゴテゴテに回ってしまった
それならGoogleが並行処理のフレームワークを作ってくれるのかと期待していたが
その気配は全くなく使いにくいcontextのみを放り投げた状態でさあ作れと言った状態
そりゃ普通のユーザーは付いてこれない
2022/09/05(月) 06:36:04.94ID:oqoL/iqD
マルチコアを効率よく使うってのがそもそもコンセプトで作られたんだがNodeみたいにしろって意味わからん
2022/09/05(月) 07:31:00.89ID:yL+fAGmc
Goのようにマルチコアを効率よくスケジューリングできて
Goのgoroutineのように多数のタスクを身軽に簡単に起動できて
Goのようにそれらタスク間でchannel通信をすることができて
それらに加えてFuture / async / awaitもサポートしているプログラミング言語がありますよ

偶然ですがその言語は
Goと同じくclassや継承がなく
Goと同じく例外try-throw-catchもなし
2022/09/05(月) 09:08:23.21ID:wt43bW0T
>>558
まずpromiseがどう有利なのか自分の口からどうぞ
そこにメリットを見いだせないから無視されるんだよ
2022/09/05(月) 10:05:06.21ID:rnwYkZ6l
Goのモデルと比較してのpromiseの優位点としてはこんなとこかな
・一般に、並行性が多少犠牲になる代わりに並行処理の複雑性を局所化する方向へとデザインが誘導される傾向がある。結果としてバグが入り込みにくい。
・ワークフローを集約して記述しやすいため可読性保守性に優れる。
・(channelではなく共有メモリを使う場合と比較して)処理結果を他のスレッドで利用する際にデータ競合が生じない。
・channelと比較して、結果として単一の値を生成するというセマンティクスが型として明確に表現される。デッドロックや閉じ忘れの心配もない。
2022/09/05(月) 10:15:26.20ID:098gBdTn
うーん今の時代にpromiseの利点を理解できない人がいるとは驚きですが仕方ない出血大サービスだ

まず最初にマルチコアを活かすという点についてだが
基本的にゴールチンのような仕組みでは全く活かせないという点を強調しておく
まともにマルチコアのCPUの性能を引き出せるのはSIMD命令を使った計算のみ
SIMDが何なのかわからない人は調べてください
SIMD演算を直接言語でサポートしていないので計算の高速化は論外
ただのマルチスレッドと変わらない
マルチスレッドはOSレベルで実装されており
コンテキストスイッチの負荷も高くCPUキャッシュも消えるし
マルチコアを活かすような作りになってないのはご存知の通り
2022/09/05(月) 10:28:17.92ID:FE5GsYYc
>>562
嘘ついちゃだめ
promiseでもデッドロック起きる
2022/09/05(月) 10:29:00.06ID:FE5GsYYc
データ競合も起きる
2022/09/05(月) 10:37:15.25ID:098gBdTn
次にpromiseの利点について

並行処理の考え方としては大きく以下がある

1.処理をシーケンシャル実行して1つずつ結果を受け取る
Aが終わったらBを実行して
Bが終わったらCを実行する

2.複数の処理を同時に実行して結果をまとめて受け取る
A、B、C...の処理を同時に実行してその結果をreduceして受け取る

3.ストリーミングモデル
いわゆるproducer/consumerに代表されるようなモデル

1と2についてはpromiseで全て安全に楽に実装できる
ゴルーチンとchannelを使った実装なんか考えたくもない
100%デッドロックが起きる

3についてはゴルーチンとchannelが本来想定してるモデルなのだが
これを適切に実装するのが難しい
CでBlockingQueueの実装したことがある人は分かると思うが極めてデッドロックが起きやすい
複数のproduer/consumerを生成したい場合など考えたくもない
さらにこのモデルの場合は基本的に大規模な分散環境で実行することがほとんどである
シングルノードでproducer/consumerなどサンプルコードでしか有り得ない
こういう用途では複数ノードのソケットにリクエストを投げて結果を待つということになるので結局2に帰着される
2022/09/05(月) 10:37:39.78ID:098gBdTn
つまりpromiseがあれば全ては安全に解決される
ちなみにpromiseはスレッド実装する必要はないことに注意
rustはスレッドで実装されているがNodeはノンブロッキングIOを使っている
他にもグリーンスレッドを使うなどいろいろある
言語側が安全性を担保できるように実装できるのだ
そしてpromiseを型安全に実装するためにはジェネリクスは必須である

以上が私の考える
「ゴルーチンは実装が中途半端で実際のユースケースを考えた場合に非常に残念なことになっている」理由である
反論があればどうぞ
2022/09/05(月) 10:37:59.16ID:rnwYkZ6l
そりゃpromiseでも共有メモリ触ったり外部のリソースをロックしようとしたりすればデッドロックするでしょう
promiseモデルとは関係ない話
2022/09/05(月) 10:56:03.27ID:88BZgezt
>>560
その言語はRustだな

>>565
Rustならデータ競合が絶対に起こらない
データ競合を起こすコードはコンパイラがエラーにできる言語仕様

>>567
ちょっと違う
RustのFuture(=Promise相当)はOSスレッドとは全く別で関係なく
Goroutineとほぼ同様の気軽に大量に作れる非同期タスクとして扱える
もちろん安全に解決できる

今回の話で言えば大雑把に分けるとRustは3種類ともサポート
① Futureおよびそのasync/await
➁ Goと同様のchanel
③ メモリ競合を絶対に起こさない安全な共有メモリ
2022/09/05(月) 11:03:44.74ID:098gBdTn
>>569
なるほど流石Rust
2022/09/05(月) 11:12:30.51ID:098gBdTn
ぐちぐち言ってきたが
Goにはゴルーチンとchannelとcontextという良いプリミティブがあるのだから
適切にpromiseを実装して使えるようにして欲しいということ
であれば並行処理がメインのアプリにおいては第一選択にもなり得ると思う
ジェネリクスも入ったのだしやれるはずなんだよ
Googleがもうやる気ないのかもしれないけど
2022/09/05(月) 12:10:29.88ID:E0SFrHzH
>>568
channelと比較してデッドロック起きないとか痛い事言っといてそれはないわw
2022/09/05(月) 17:07:29.06ID:oqoL/iqD
Nodeしかさわったことないから詳しくは知らんけどasyncawaitモデルだと
async関数を使うには呼び出し元にどんどんasyncが汚染されて使いづらいイメージがあるな

その点Goは同期的なコードの一部を並行処理にするってのが非常にやりやすいと思う
タイムアウト処理もselectで簡単に実装できるし、シンプルなfork joinだったらsync.waitgroupで楽に実装できるし
何も困ったことがないな

そんなに優位性があるとは全然思わない
2022/09/05(月) 21:20:50.97ID:MMezNWAp
>>573
Goは見かけ同期と誤認するけど
同じOSスレッド上でもメインや複数のGoルーチンがスケジューリングされて交互に非同期で動いているよ

例えばGoで
 func1()
 func2()
 func3()
と見かけ同期に書いているのは
async/await対応言語で
 await asyncfunc1()
 await asyncfunc2()
 await asyncfunc3()
と書いた時と同じ状態
つまり見かけ同期のGoの実態は非同期

「Goは最初から全てがasync汚染されているためasync汚染に気付かずに済む」が正解
2022/09/05(月) 22:10:30.31ID:oqoL/iqD
>>574
goキーワードなかったら同期的に動くだろ
ライブラリの中でgoキーワードが使われてるから暗黙的に使われるが正しいね。

非同期にしたい部分でgoをつけるのであってつけてないのに全部非同期だってのはおかしな話だな
2022/09/05(月) 22:24:10.45ID:M8mFZMdW
>>575
それは見かけ上だけ
goを付けなくても読み書きなど含めて時間がかかるものは
見かけ上だけ同期ブロックしているが
実際には非同期で動いており裏で別のgoroutineにスケジューリングされている
そしてその読み込みや書き込みが可能となると
見かけ上だけ同期ブロックしていたところへスケジューリングが戻る仕組みであってGoは常に非同期に動いている
2022/09/05(月) 22:30:51.53ID:oqoL/iqD
ユーザーに見せてるのは全てブロッキングなコードなわけじゃん
それをgoキーワード使って複数立てた時に非同期で動くって話で、単体の場合はあくまでも同期的に動くよね

mainルーチンでhttp.getってやったら同期的に動いてるよね?
これを別のgoroutineを立てて複数立ち上げればブロックする後は勝手に非同期で動くってだけの話

async汚染はユーザー目線で言ってるね
Goのモデルは既存のコードや構造に手を加えずに一部だけを非同期にするのが容易、これが一つのメリットではあると思う
2022/09/05(月) 22:40:11.19ID:oqoL/iqD
Node/Denoの作者も同じこと言ってるし、async/awaitモデルの方が優れている一言も言ってないな
むしろGoのモデルをほめてるわ
https://mappingthejourney.com/single-post/2017/08/31/episode-8-interview-with-ryan-dahl-creator-of-nodejs/

必死にasync/awaitの方が優れてるとか言ってるみたいだけど、逆にGoのモデルの方が使いやすいって人もいるわけだよ
自分の意見が全てだと思わない方がいいんじゃないかな
感覚的な話で優れてるって言われてもね
2022/09/05(月) 22:48:10.04ID:bm2FICIw
>>577
> ユーザーに見せてるのは全てブロッキングなコードなわけじゃん

それは見かけだけだな
例えば>>574
| await asyncfunc1()
| await asyncfunc2()
| await asyncfunc3()
これも(同じく見かけだけ)全てブロッキングな同期で実行されるコード
そしてGoと同様に実際には裏で非同期に動く

> 単体の場合はあくまでも同期的に動くよね

それは見かけだけ
つまりasync/await対応言語がawait文で見かけだけ同期的に動いているように見せかけるのと完全に同じ
2022/09/05(月) 23:00:13.19ID:oqoL/iqD
うんだからユーザーに見せるコードが同期的なことろがわかりやすくて良いって言ってるんだけど?最初その話してたよね?同期的なコードって言ってるよ?
裏でepollやら使ってて非同期だから云々の話はしてないんで
ちなみになんでいちいちID変えるの?
581デフォルトの名無しさん
垢版 |
2022/09/05(月) 23:32:28.26ID:9iTWKe04
>>576
>見かけ上だけ同期ブロックしているが
>実際には非同期で動いており裏で

んなこと言ったらIO操作のあるあらゆる言語が低レベルでは非同期で動いてるじゃんよ。
582デフォルトの名無しさん
垢版 |
2022/09/05(月) 23:43:38.07ID:iWQD5HeB
C10K問題から非同期が流行ったのに、メモリーを使いまわしてたら意味ないのでは?

一つのスレッドに一つのスタック、典型的に一つのスタックは1MB準備される。
10Kのスレッドがあれば、10GBのメモリーが必要。
256MBのSUNでは無理。

でも、非同期でも1MBの配列を用意してデータが届くたびに書き足していくなら同じことでは?
583デフォルトの名無しさん
垢版 |
2022/09/05(月) 23:47:49.38ID:iWQD5HeB
ウェブ・サーバーが静的なファイルを送り出していた2000年ごろなら非同期が大それた力だっただろうけど。

全てが動的な現代において、非同期はめんどくさいだけなのでは?
2022/09/05(月) 23:53:52.32ID:YaRYiHc+
昔より回線が安価になって接続数が多くなったんだから非同期が必要でしょ
585デフォルトの名無しさん
垢版 |
2022/09/05(月) 23:56:02.82ID:iWQD5HeB
どういうことですよ?
586デフォルトの名無しさん
垢版 |
2022/09/06(火) 00:05:01.14ID:btul1bBo
静的なファイルを送るだけなら。

カーネルの送信バッファが空くのを待つ

送信バッファと同容量だけ非同期にファイルの読み込みを開始する

ファイルデータが読み込まれると、送信を開始する

最初に戻る

この手順で、典型的なTCP通信なら20KB以下のメモリーで足りる。
でも、動的なコンテンツ生成では、そうはいかないのでは?
2022/09/06(火) 00:56:32.90ID:jgCBXC4T
ヒント:httpは同期通信
588デフォルトの名無しさん
垢版 |
2022/09/06(火) 01:32:17.99ID:h7zKo1Kf
>>563 のここがよく分からない

> まともにマルチコアのCPUの性能を引き出せるのはSIMD命令を使った計算のみ

SIMD命令付きのシングルコアCPUもあったじゃん。
古いけど MMX Pentium とか Pentium III とか。
この時代はSIMD命令は何を引き出してたの?
2022/09/06(火) 02:05:21.99ID:haU306kC
>>566
1なんか一つのgoroutineに上から並べるだけで良いじゃん。
2022/09/06(火) 02:06:28.41ID:haU306kC
えっ?もしかしてこの人
>>574
でもまだ理解してないの?
2022/09/06(火) 03:40:36.05ID:4pNI/aXz
>>587
httpを同期で実装するなんて昔のダメなシステムと完全ブロックしても困らない末端クライアントだけたぞ
httpクライアントとして動作する時もサーバーで使うなら同期ブロックしてしまうとスレッド資源を無駄に専有
だからhttpを使うなら何らかの非同期にするのが当たり前
592デフォルトの名無しさん
垢版 |
2022/09/06(火) 06:52:34.65ID:JHpT8XfS
>>574
多くの言語でasync/awaitキーワードだらけになって反吐が出る気分だわ、これを良いと考えた人たちを殴りたい...
goにpromise/futureなんて絶対不要、こんなの必要だと思ってる人相当アホやぞ

>「Goは最初から全てがasync汚染されているためasync汚染に気付かずに済む」が正解
なるほど意味わからん
asyncキーワードなんて無いのにスケジューリングで同期実行されるから汚染?ww新理論w
2022/09/06(火) 08:04:56.91ID:g0koBBSB
>>566
1なんてそのまま関数並べるだけだし
2はN件goroutine立ち上げてたらN回チャネル待ち受ければいいだけだよね
タイムアウトもselectで容易に実装できる

100%デッドロックするとか言ってるけどそれはGo超初学者が使った時の話かな?
仮にデッドロックしても検知機構働いてちゃんと落ちるし何が言いたいのか
2022/09/06(火) 10:57:52.38ID:ItiT2cL1
>>588
その時代のことはよく知らないので
気になって調べてみたがwikipediaによると
2クロックで実行するという実装になっていた模様
なのでその時代に関しては128ビット幅のレジスタを使えるというアドバンテージしかなかったとのこと
2022/09/06(火) 11:23:36.25ID:7Nc33VtP
>>591
通信プロトコルとhttpサーバー/クライアントの実装が区別できないおバカさん乙w
そんなんでよくGoなんて使えるな
2022/09/06(火) 14:37:15.63ID:ax+JnAgH
今回は実装の話だからサーバー上なら今どきは非同期で実装で合ってると思うよ
2022/09/06(火) 16:35:51.33ID:E35zydsp
>>596
文脈読めないおバカさんその2乙w
2022/09/06(火) 16:56:04.53ID:rOGll//o
>>593
その通りだな、安易に実装できるものを標準で欲しがる理論がわからんわ
多くの言語のfutureなんてデータの結果受信同期待ちが起こるだけだし、goのcontext.WithTimeoutは
他の言語では全く実装できていないfutureのプラス機能のようなもので、goはより進んでいると言える
一方promise的なもの、つまり複数のgoroutineを束ねて制御したい人は、欲しい人もいるかもしれないが
goで書いたpipeline処理は手動で書くからこそきめ細かい制御が出来るので、無作為にこれとこれを並列、
これとこれを非同期だけど同期的に実行にしたいとか、効率を考えたらこの流れを組み替えられることには
ほとんど意味もないね。
例えばJSでPromise.allとかすべてを非同期並列に実行して成功の可否で分岐したいなんて、同じ状態が
goroutineとチャネル待ち受けで出来てしまうわけで、それを仰々しいライブラリにする意味が分からん
599デフォルトの名無しさん
垢版 |
2022/09/06(火) 17:02:41.68ID:rOGll//o
上では良いことだけ書いたけどif err != nullはもうそろそろダルいので何とか手を打ってほしいわ
副作用のある関数ではgoの第二の戻り値がerrなのは、もはや言語仕様なので別言語でいう
Option/Result/Eitherみたいなものは必要ないにしても、?.のようなNull条件演算、合体演算
のようなErr条件演算が欲しい
2022/09/06(火) 18:25:37.98ID:rAtefbER
きめ細かい制御してるか?
goのモデルは良くも悪くも作った水路に水を流すだけで、実際にその中のどこでどのようにブロッキングが発生するかは気にしないのが正しい使い方
どっちかというとpromise系のほうが制御は明示的だよ
2022/09/06(火) 20:30:57.65ID:haU306kC
きめ細かいGoのpipelineって、もしかしてGoあんまり書けないのでは…?
ランタイムの大勝利な事の方が多いぞ。
602デフォルトの名無しさん
垢版 |
2022/09/07(水) 08:09:00.20ID:KZnrapZJ
きめ細かいでしょう?
チャネルが1個なら並列性が1つでブロッキング出来るし、並列性を持たせたいなら複数のチャネル幅を
用意すればいいだけ1段目のパイプライン処理が終わったすぐ後に、次段のパイプライン処理を普通に書く
ことができるし、sync.WaitGroupを使えばパイプライン中の中間データへ同期制御もできる
それ以外にGoで書かれた多くの優れたパイプライン処理は、キャンセルを考慮している。
ブロッキングが発生するかは気にしないなんて事はなく、チャネルのselectでブロッキングが入ることは普通に
当たり前だから気にしないだけ
https://go.dev/blog/pipelines

世にある多くのpromiseはキャンセルやタイムアウトは考慮していない場合が多い、All or Nothingでしかない
大雑把な実行制御でしかない。多くは流れるようなデータの受け渡しもできない。
実行順を決めるだけで、特定の処理に多重度を持たせるとかそんなことは出来ない
これは多くがpromiseというものが非同期処理をベースにした疑似的な実行順制御の仕組みだけであるから
2022/09/07(水) 13:37:16.25ID:ossJLtb4
>>599
nullじゃなくてnilな
2022/09/07(水) 16:59:11.50ID:GTdTGsfv
>>598
そもそも、複数のgoroutineを束ねて使いたいという要請でsync.WaitGroupは作られてるから、自前で作る意義すら無いんだよな
グループを待つ、のだから
2022/09/08(木) 16:15:42.84ID:+22QbHY9
>>593
だからその程度のことしかしないのにわざわざゴルーチンだのchannelだのselectだのを書かなきゃいけないことがだるいと言う話だよ?
書けるか書けないかで言ったらそりゃ書けるでしょw
あと普通に刺さる可能性が高いと言うことを言ってる
2022/09/08(木) 22:55:49.37ID:AWp4/fcz
ホントにGo書けないんじゃないの…?
2022/09/09(金) 08:28:18.12ID:5SEsta+Y
意味わかんね

>>566 では promise の利点をこう書いてた

> 1と2についてはpromiseで全て安全に楽に実装できる
> ゴルーチンとchannelを使った実装なんか考えたくもない
> 100%デッドロックが起きる

それに対して >>593>>598 が goroutine とチャネルで簡単に実装できるって言ったら >>605

> わざわざゴルーチンだのchannelだのselectだのを書かなきゃいけないことがだるいと言う話だよ?

「だるい」なんて話、一切してなかっただろ。
2022/09/09(金) 11:21:59.96ID:8m5pePL+
>>607
マジでアスペか?
promiseの方が明らかに楽でバグが生まれない
これはこれまでの議論の流れで一貫してる主張

なんでリクエストのデータ受け取るのにgoルーチンだのchannelだのselectだの書かなきゃならんのだよ

そしてpromiseを実装するのは我々ではなくGoコンパイラの開発者たちだよ
2022/09/09(金) 12:35:07.97ID:OI70qo+4
promiseって普通awaitするのが普通だよね?
goもチャネルも使わない状態でhttp.Get呼ぶのと全く同じだよ

goroutineの中で実行すれば勝手に非同期になるしfork joinしたいならチャネルがwaitgroup使うだけの簡単なお仕事
2022/09/09(金) 12:39:54.70ID:ppztOn1H
>>608 >>607
まずは「goroutine&channelだと100%デッドロックが発生してpromiseだと発生しない状況」について戦えよ。

だるいとかより興味あるわ。
2022/09/09(金) 13:19:10.61ID:WCKL/dzA
>>608
「promiseの方が明らかに楽でバグが生まれない」
そんな統計は1つもないければ、あなたの貧相な頭の中だけですよね?それを証明しなさいと暗黙的に問われているのがわかりませんか?

「なんでリクエストのデータ受け取るのにgoルーチンだのchannelだのselectだの書かなきゃならんのだよ」
じゃあなんで、promiseなんていう出来の悪い非同期処理のために作り出された愚物を、真にマルチプロセスに対応するgoで
エミュレーションしなきゃならないんですか?あなたのためだけですよね、ほとんど誰も欲しがっていませんけど?
このような需要がない機能を、標準ライブラリに求めるものではありませんし、あなたの隠れた真の心は
「学ぶことをしたくない」だけでしょう、ご自分でも気づいてないと思いますが
C#やScalaあるいはJSしか出来ないなら素直にチームに報告しましょう、あなたのやる気を引き出すためだけに我儘を際限なく
広げても誰も理解してくれませんし、当然、味方にもなってくれないでしょう。だってやる気が無いんですから。
言語の基本的な考えが違うのに、他の言語に似たような雰囲気を求めるのは間違っていますし、なおかつ結局同じコードを
書いてしまうなら乗り換えるような利点をすべて消し去るでしょう

「そしてpromiseを実装するのは我々ではなくGoコンパイラの開発者たちだよ 」
実装しないと思いますね、あなたのゆがんだ考えでは超保守的なgoチームを説得するのは無理でしょう。1つも有益な
調査結果なり、推測なりが述べられていません。あなたが「ルーチンだのchannelだのselectだの書かなくちゃならない」と
我儘を言ってるようにしか見えません。仮に万が一億が一、必要だとしてもGithubに個人実装のライブラリとしてあるでしょう
2022/09/09(金) 13:32:44.23ID:eDV4BhqD
まあasync/awaitのほうが初心者に対するハードルは低そうな気はする
初心者が雑にchannel使ってるとたいていバグってるわ
2022/09/09(金) 13:34:32.33ID:KNCe5V0g
async/await手軽で簡単だけど複雑なことやろうとすると難しい
Goroutineとchannelはasync/awaitと比べると確かにとっつきにくいが複雑のことも組み合わせで上手く実現できる応用力がある
2022/09/09(金) 14:08:59.93ID:+r9uXbjm
>>611
そういうストローマン論法は俺には通用しないって
2022/09/09(金) 14:53:32.39ID:5SEsta+Y
promise の利点まとめ

- goroutineとchannelを使うと100%デッドロックが起きるが promise だと安全に実装できるものがあるらしい。具体例は不明。
- >>605 にとってだるくない。
2022/09/09(金) 15:05:25.55ID:+6O98yvA
非同期で順列な処理やる場合はasyncのがわかりやすい
並列にタスクいっぱい撒いてなんかやるみたいなのはchannelって印象
2022/09/09(金) 15:59:29.38ID:WCKL/dzA
promiseに似てるけど、全く違うものはerrgroup.Groupと呼ばれます。これもpromiseなんぞと比べれば
コンテキストなどと組み合わせキャンセルやタイムアウト処理が容易にできますし、実行順の制御や包括した
エラー処理以外にパイプラインまで簡単に拡張できます。

例1:ページをフェッチして全ての処理が終わるまで待つグループ制御(1つでもエラーならエラー処理)
https://pkg.go.dev/golang.org/x/sync/errgroup#example-Group-JustErrors

例2:単純な並列タスクを同期するためのグループ制御
https://pkg.go.dev/golang.org/x/sync/errgroup#example-Group-Parallel

例3:多段ステージを設けたパイプライン処理をグループ制御
https://pkg.go.dev/golang.org/x/sync/errgroup#example-Group-Pipeline

例1、例2はJSでいうPromise.all() のような動きをしますがpromiseなんていう融通の利かない非同期のため
だけの劣った機能より格段にシンプルな仕組みです。
上の例でいえば、並列タスクなどではchannelを使用せず、複数起動された軽量ルーチェンから元ルーチェンへ
results配列の結果を戻していますが、これは並列タスクが一段で終わるからです。
次の(例3の)pipeline処理にあるように、並列と並列が連鎖する多段処理においてはchannelのような
仕組みを使うのがとても合理的です。もちろん、処理の終わりの同期のために、selectによる結果受信待ちは
入りますがこれはデットロックではありません

もともとJSのPromiseがなぜあるかといえば、同じプロセス空間で疑似的な非同期処理による実行制御を行うため
だけの仕組みです。このため、特定の変数(結果を格納する配列や変数)に同時にアクセスされるという考えは
ありませんし、そのような(ロックや待ち)制御は必要ありません。現実に同時に動いていないのですから

隣国のアジア人コミュニティに「ストローマン論法」という言葉を連呼するキチガイ集団がいましたが、本当のバカだった
2022/09/09(金) 18:31:46.48ID:RxEWaepL
結局何がChannelに無くて、何がPromiseでしか解決できない問題なの?
Promiseを解決せずに持ち回ること?
2022/09/09(金) 23:05:27.12ID:zn1Qb1Bt
>>617
例1がすでに全然シンプルじゃないw
しかもレスポンスを返さない例で意味ないww
それ以外にも落とし穴満載

現実にこんなコード書いてるやつばっかりならバグりまくってヤバそう
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。