2021/11,江端さんの忘備録

我が家のダイニングテーブルは、4人用なので、家族全員が着席できる ―― はずなのですが、

Our dining table is designed for four people, so the whole family can be seated, however,

感染予防用の2つのパーティションを購入後、そのパーティションに書類を貼りつけるようになり、

After purchasing two partitions for infection prevention, we started attaching documents to the partitions.

娘たちが、読書したり、スマホでアニメ見たり、レポート作成したり、製図を書いたり、リモート授業を受講したり、

My daughters are reading, watching cartoons on their phones, writing reports, drawing, taking remote classes, etc. on the table,

テーブルの上は、ノートパソコン、各種資料、請求書、書籍等が散乱している状態となっており、

with being cluttered with laptops, various documents, invoices, books, etc.

テーブルの定員は、今や『2名』が上限となっています。

The maximum number of people at a table is now just "two".

-----

先程、パンケーキとスクランブルエッグを作り、皿に盛って着席しようとしたのですが、すでに、嫁さんと次女によって、テーブル席が占拠されていました。

I had just made pancakes and scrambled eggs, put them on plates and was about to be seated, but the table was already occupied by my wife and second daughter.

仕方がないので、トレイに皿を置いて、

I had no choice but to put my plate on the tray.

『部屋で食べてくる』

"I'll eat in my room."

と言って、階段を上がり始めました。

I said, and started up the stairs.

次女:「二階席は、比較的、空席がございますーー」

Daughter: "The seats on the second floor are relatively empty.

私:「ないわ! 二階席のテーブル(私の机)も、プログラムリスト、参考資料と書籍で、満席だ!!」

I: "No! Even the upstairs table (my desk) is full, with program lists, reference materials and books!"

と、愚痴を言いつつ、自分の部屋に向かいました。

I complained and went to my room.

未分類

もう、腹を立てるのも面倒になってきたので、情報開示請求をして、オンライン提出しない政治団体を、全部、実名開示してやろうと思います。

この書類を、300円分の印紙を張って、ここに提出すれば良いみたい

以前、国土交通省に「飛び込み自殺」の人数、時間などについて請求したのですが、すっかり忘れてしまいました。

まあ、書式不備があれば、連絡がくるでしょう。

腹を立てているだけでは、健康衛生上もよろしくないでしょうし。

 

 

 

2021/11,江端さんの技術メモ

  • Go言語のコーディングしている最中に、バグを指摘してくる(お前はツンデレ彼女か)
  • 適当なメソッドを書き込むと、自動的にimport関数を付け加えてくるところ(お前はお袋か)
  • バグではないけど、不効率なコーディングをしていると、もっと良いやり方を提案してくる(お前は構いたがりのメンターか)

―― なんか、ちょっと怖い

 

 

2021/11,江端さんの技術メモ

https://teratail.com/questions/370090?nli=619ad631-d4fc-405f-a649-44670a040506#reply-502318

もの凄く助かりました。

nobonoboさんに心からの感謝を

C:\Users\ebata\goga\3-10

/*
いっせいブロードキャストをするのに一般的に使われているのはPubSubと呼ばれる方式です。
サブスクライブを複数あらかじめおこなっておき、パブリッシュでメッセージを送ると
複数のサブスクライブ先に同じメッセージを配信するというものです。
おそらくこの方式は発見済みで、想像するに複数のサブスクライブ先をループで巡って
複数回送信することでブロードキャスト相当を実現するのではなく、もっと真に
ブロードキャストしたいということが質問者さんの意図なのかなと。

そういうものを実現するのに「sync.Cond」という標準ライブラリ機能があります。
これの活用方法は実はちゃんとした実例が見つけにくいです。たいてい前者のやり方で済まして
しまっているのと、sync.Condの挙動は若干わかりづらいです。

すこし解説は端折りますが、以下のように記述することで実現できると思います。

ポイントは

タイミングだけをsync.CondのBroadcastで伝える
複数のタスクには共有メモリを通して渡したいメッセージを伝えます
送る方も受ける方も排他ロックを併用するのがCondの使い方でロック期間であれば
共有メモリをコンフリクトなくアクセスできます

この方法はPubSubにくらべ、共有メモリをすべてのgoroutineタスクに伝播したか
どうかを保証する仕組みがないです
つまり、この方法は「低頻度のイベントを大量のタスクに配信」するか、もしくは
「最新の値さえ受け取れればOK」という用途向けです。
*/

package main

import (
	"fmt"
	"log"
	"sync"
	"time"
)

type BroadCaster struct {
	cond *sync.Cond
	id   int64
	msg  string
}

func (bc *BroadCaster) Send(msg string) {
	bc.cond.L.Lock()
	defer bc.cond.L.Unlock()
	bc.id++
	bc.msg = msg
	bc.cond.Broadcast()
}

func (bc *BroadCaster) Recv(last int64) (int64, string) {
	bc.cond.L.Lock()
	defer bc.cond.L.Unlock()
	for bc.id == last {
		bc.cond.Wait()
	}
	return bc.id, bc.msg
}

var (
	broadcaster = &BroadCaster{
		cond: sync.NewCond(&sync.Mutex{}),
	}
)

func task(i int) {
	log.Println("task:", i, " start")
	defer log.Println("task:", i, " stop")
	last := int64(0)
	for {
		id, msg := broadcaster.Recv(last)
		last = id
		log.Println("task:", i, msg)
	}
}

func main() {
	for i := 0; i < 3; i++ {
		go task(i)
	}
	for i := 0; i < 3; i++ {
		time.Sleep(1 * time.Second)
		broadcaster.Send(fmt.Sprintf("hello, world: %d", i))
	}
	time.Sleep(1 * time.Second)
}

Keyword sync.Cond, sync.Broadcast,

参考文献: sync.Cond/コンディション変数についての解説

2021/11,江端さんの忘備録

私たち、日本人は『日本人だけが英語が苦手である』と思いがちです。

We Japanese tend to think that "only Japanese people are bad at English".

しかし、『英語に愛されない外国人』はいます ―― 恐らく、山のようにいます。

However, there are foreigners who are not loved by English language -- probably a lot of them.

-----

今年の9月に、リモートで国際学会での発表と聴講をしていました。

In September of this year, I was remotely presenting and auditing at an international conference.

日本時間でスタート18:00、終了が02:00という、洒落にならない時間になりましたが ――

The event started at 18:00 Japan time and ended at 02:00, which is an unbelievable time, however,

それでも、飛行機に乗って、ホテルに宿泊して、レストランでメニューに困り、時差ボケで最低の体調で聴講することを考えれば、

Still, considering that I had to get on a plane, stay in a hotel, have trouble with the menu at a restaurant, and listen to a lecture in my worst condition due to jet lag..., this is a

『天国』

"Paradise"

です。

開催後のアンケートで、『今後もリモートでの開催を希望するか』という項目のアンケートには、5段階の評価で"5"を付けました。コメント欄にもその旨を記載しておきました

In the questionnaire after the conference, I gave a rating of "5" on a 5-point scale when asked if I would like the conference to be held remotely in the future. I also mentioned this in the comments section.

ま、それはさておき。

Well, that's beside the point.

-----

学会発表で、東欧の若い研究者(女性)の発表を聴講していたのですが、自信なさげで、声が小さく、論旨も良く分からない ―― という、発表がありました。

At the conference, I was listening to a presentation by a young researcher (female) from Eastern Europe, who seemed unsure of herself, her voice was quiet, and her argument was not clear.

『あ、これ、大学生だ。しかも、多分、教授にごり押しされて、発表させられたタイプだ』

"Oh, this is a college student. And she's probably the type of guy who was pushed into doing a presentation by her professor.

と、看破しました。

I've seen it through.

で、予想どおり、彼女は、座長(セッションの議長)からの質問に対して、全く答えられませんでした。

So, as expected, she could not answer any of the questions from the chairperson (the chair of the session).

答えられないプレゼンテータに対して、"evaluate"の言葉の意味を、座長が教えているのを聞いて、『・・・く、空気が重い』という苦痛の時間を体験しました。

I experienced a painful time when I heard the chairperson telling the presenters who couldn't answer the question what the word "evaluate" meant, and the air was heavy.

この質問時間は時間切れで終了したのですが、なんとも後味が悪いものでした。

This question period ended when time ran out, but it was a very bad aftertaste.

-----

この場合の正解は、

The correct answer in this case is

『質問の内容が分からないくても、沈黙せずに、でたらめな英語ででたらめな回答を一方的に喋るまくる』

"Even if I don't understand the question, I don't stay silent, I just go on and on with my bullshit answers in bullshit English"

です。

これは、実質「沈黙」と同じことです。

This is practically the same thing as "silence".

しかし、聴衆が「失笑」と「嘲笑」と「生あたたかい優しい目」で見てくれる、という効果があります。

However, the effect is that the audience will look at me with "guffaws", "ridicule" and "warm, kind eyes".

また、私と同じような「英語に愛されないエンジニア」には、その戦略(でたらめな英語で、でたらめな回答を押し通す)を理解して貰えます。

Also, "engineers who don't love English" like me can understand my strategy (use bullshit English, push through bullshit answers).

上手く行くと、そのセッションが盛り上がります。

If it goes well, the session will be a lot of fun.

―― こんなに英語がダメダメな奴が、こんなもしょーもない質問しているなら、私も質問してみようかな

"Let me try a question, if the guy whose English is this bad is asking such dumb questions"

という気持ちになるようです。

Such feeling seems to coming to the audience, I think.

結果として、私の参加したセッションは大いに盛り上がって、喜んだ座長がリモートで記念写真を取っていたくらいです。

As a result, the session I attended was so exciting that the delighted chairperson even took a commemorative photo remotely.

-----

「英語に愛されないエンジニア」は、インターナショナルで役に立ちます。

The Engineer Who is not Loved by English" is useful internationally.

『場』のしきい値を思いっきり下げて、みんなをリラックスさせます。

Lower the threshold of the "field" as much as possible to make everyone relax.

もちろん、公の場で『道化』になる覚悟は必要ですが ―― まあ、肚を括れば、なんとかなります。

Of course, you have to be prepared to be a clown in public, but if you have the courage, you can do it.

どうせ、その時を過ぎれば、誰もあなたのことなど覚えていません。

After that time, no one will remember you.

2021/11,江端さんの忘備録

「どこから手をつけたらいいのか分からない」ってこと、結構ありますよね。

"I don't know where to start" is pretty common.

私の場合、毎月のコラム原稿がそれです。

In my case, it's my monthly column manuscript.

とりあえず、思いつく図表を適当な枚数描いて、それを並べて、その図表に間に文章を流し込みます。

For now, draw as many charts and tables as I can think of, arrange them in a row, and pour text in between them.

ぶっちゃけますけど、

Let me be frank.

―― 完成のイメージなんか、全然持たずに、文章作成しています

I'm working on the text without having any idea of how it will turn out.

-----

ところが、

However,

『図表や文章の位置を変えたりしながら調整していくと、なんか、ちゃんとしたコラムになっている(ように見える)』

"It comes to be like a proper column when I adjust it by changing the position of figures and sentences"

のです。

これが、パソコン時代の、文章作成作業のミラクルです。

This is the miracle of the writing process in the computer age.

『パソコンがない時代の人は、どうやって資料や作品を作成していたのだろうか』と考えるだけで、尊敬できてしまいます。

"How did people create materials and works of art when there were no computers?" Just thinking about it makes me respect them more.

-----

文章を書くのが苦手という人に、私ができるアドバイスがあるとすれば、

If there's one piece of advice I can give to someone who has trouble with writing, I say to them,

『荒唐無稽で、デタラメで、論理破綻している文章を、まず、ザーっと100行くらい書いてみろ』

"First, write a hundred lines of ridiculous, bullshit, logic-defying text"

と言います。

その後で、その文章をバラバラにして再構成します。

After that, take the text apart and reconstruct it.

そして、これが大切なのですが、『未完成でもいいからネット等で公開する』ことです。

The most important thing is to publish your work on the Internet, even if it is not completed.

『ネットの向こう側で、嘲笑、失笑されている』と実感することが、大切です。

It is important to realize that you are being ridiculed and laughed at on the other side of the Internet.

実際にこの日記も、「最初の1行」を書いた後は、だらだらと適当に文章を書いて、それを並びかえたものです。

In fact, in this diary, after I wrote the "first line," I just wrote random sentences and rearranged them.

-----

『江端のことは知らんが、私は最初から理路整然と文章を書けるぞ』と主張をする人がいても、私はその人の言うことを信じませんし、もし、それが本当であったとしたら ―― 私は、その人、嫌いです。

If someone claims, "I don't know about Ebata, but I can write in an orderly fashion from the beginning," I don't believe them, and if that were true -- I hate that person.

2021/11,江端さんの忘備録

若い人に『手痛い失敗』をさせないことが大切だ ―― と思っています。

I believe that it is important not to let young people make "painful mistakes".

昔、どんなに説明しても『プログラムローディング方式はダメだ』と信じる部長がいて、研究ユニットの研究開発が滞ったことがありました。

In the past, there was a department head who believed that the program loading method was no good, no matter how much I explained, and the research unit's R&D was stalled.

もちろん、今や、プログラムローディング方式の一つであるJavaScriptは、Webブラウザで、複雑な物理計算結果を、その動きを示しながら表示できるまでになっています。

Of course, JavaScript, one of the program loading methods, is now capable of displaying the results of complex physical calculations in a web browser, showing them in action.

これは、ネットワークの速度や、コンピュータのパフォーマンスが、当時とは比較にならないほど向上したからです。

This is because the speed of networks and the performance of computers have improved to a degree that is unparalleled in those days.

ところが、その部長は、若いころの『プログラムローディング方式』の研究で、手痛い失敗で、回復できないほどの負の記憶を植えつけられたらしいです(と、他の人から聞きました)。

However, the head of the department had made a painful mistake in his research of the "program loading method" when he was young, and had been imbued with negative memories that he could not recover from (or so I was told by others).

当然、その部の研究は、プログラムローディング方式について、後塵を拝することになりました

Naturally, the department's research took a back seat to the program loading method.

これは、研究開発だけではなく、特許でも同じことが言えます。

This is true not only for R&D, but also for patents.

-----

上司の思い込みは、失敗の記憶とペアになって強化され、その上司の権力によって、部下にも影響を与えることになります。

The boss's assumptions are reinforced when paired with memories of failure, and the boss's power to influence his subordinates.

そして、「自分の失敗」を、「部下が成功させた」というのは、正直不愉快なことでもあります。

And to be honest, it is also unpleasant to hear that "my failure" was made successful by a subordinate.

加えて、たちの悪いことに、上司は、「ロジカルに『それが上手くいかない理由』を部下に説明できてしまう」のです。

What's worse, the boss can "logically explain to the subordinate why it won't work.

なにしろ、自分がやって失敗したのですから、そんなことは簡単です。

After all, they did it and failed, so it's easy.

こうして、生れる前のテクノロジーは、1mmの悪意もなく、組織的に運命的に潰されることになります。

Thus, pre-born technology will be systematically and fatally crushed without malice.

そして、私も、間違いなく、同じ愚を繰返していると思います ―― 『私は若手のアイデアを潰しまくっている』という絶対的な自信があります。

And I'm pretty sure I'm repeating the same foolishness -- I'm absolutely confident that I'm crushing the ideas of young people.

-----

ここから得られる教訓は、

The lesson to take from this is, like,

(1)上司は、部下の暴走を見逃す、と言う勇気を持つこと。そして、見逃すことによって、その責任が自分に返ってくるという理不尽を受け入れること

(1)The boss must have the courage of, "I will overlook a subordinate's outburst". And, by letting it go, they must accept the unreasonable results that the responsibility will come back to them.

(2)部下は、上司に研究を報告しないこと。それが成功するまでは、黙って一人で孤独にアンダーテーブルで研究を続けること

(2)Subordinates should not report their research to their bosses. Until they succeed in doing so, they need to continue their research under-table in silence and in solitude.

という、報告・連絡・相談(ホウレンソウ)のアンチテーゼが必要である、ということです。

is the antithesis against reporting, communication, and consultation

上司は部下の独断先行を苦笑いで許し、部下は自分の信じる研究を、自分の時間(睡眠時間、休日)でやるという覚悟をすることが必要です。

Bosses must be prepared to forgive their subordinates' arbitrary preoccupations with a wry smile, and subordinates must be prepared to do the research they believe in on their own time (sleep time, holidays).

コミュニケーションは大切です。

Communication is important.

ですが、非コミュニケーションも、それに劣らず大切なことなのです。

However, non-communication is just as important.

それは、この本を読んで頂ければ、理解して貰えると思います。

If you read this book, you will understand that.

2021/11,江端さんの忘備録

「萌えキャラ」というものが、最近、色々騒がれているようです ―― が、私は、妙なことに巻き込まれるのは嫌なので沈黙を決め込みます。

There seems to be a lot of fuss about "moe characters" these days -- but I don't want to get involved in anything strange, so I'll keep quiet.

私は、コラムの執筆が完了すると、イラストを描き始めるのですが、これは、私にとっては「自分に対するご褒美」みたいなものです。

When I finish writing a column, I start illustrating it, which for me is like a "reward" for myself.

まあ、私は、私のイラストに興味のある人がいるとは思っていません。

Well, I don't expect anyone to be interested in my illustrations.

実際、「自分に対するご褒美」みたいな気持ちで描いているものが、そんなに凄いものになる訳はありません。

In fact, there is no way that something that I draw with a feeling of "reward for myself" becomes great.

それに、次女が言うように 『どっかで見たようなイラストだね』という感想は、残念ながら、私も同意しています。

And, as my second daughter said, "Your illustrations look like something we've seen somewhere else," which, unfortunately, I agree with.

-----

私は、『絵を描くのが楽しい』というよりは、ドローソフト(私はSAIを使っています)を使って、『色々な技が使えることが楽しい』です。

For me, it's not so much 'drawing is fun' as it is 'being able to use a variety of techniques' with drawing software (I use SAI).

■ ここの部分だけ、切り取りたいな

- I just want to cut this part out.

■ このキャラクターは、ちょっと発光させてみたいな

- I'd like to make this character bright a little.

■ この絵は、ちょっと白黒を強めに出したいな

- In this picture, I want to make it a little more black and white.

みたいなことを、ドローソフトを使うと、チョイチョイとできる感じが好きです。

I like the feeling of being able to do things like that in a snap with draw software.

間違えた操作で、予想もしなかったような効果が出たりすると驚きます。

I may be surprised to find that a wrong operation can produce effects that I never expected.

■ 自分でポーズを取って、ビデオ撮影して、キャプチャしたものからイラストを作るのも、面白いですし、

- It's also interesting to pose myself, take a video, and create an illustration from the captured images.

■ 男性のキャラクタを使って、それを女性のキャラクタに変換したりする作業も、楽しいです

- It's also fun to take a male character and transform it into a female character.

しかし、これは、所詮は「技術」の話です。

However, this is just a matter of "technology".

私は、自分の作品を「芸術品」と思ったことは、一度もありません。

I have never considered my work to be a "work of art".

-----

私のような画才のない一技術者が、まがりなりにも、イラストを描くことを実現させてくれる、IT(パソコン)に対して、感謝をしています。

I am grateful to IT (computers) for making it possible for an engineer like me, who has no artistic talent, to draw illustrations.

私は、ドローソフトでイラストを描き始めてから、芸術品一般は勿論ですが、アニメや、それこそ「萌え絵」と言われているものや、そしてその創作者の方々に、心からの敬意を払っています。

Ever since I started illustrating with drawing software, I have had a deep respect for not only art in general, but also for anime and what is often referred to as "moe" art, and its creators.

「萌えキャラ」というものが、最近、色々騒がれているようです ―― が、私は、妙なことに巻き込まれるのは嫌なので沈黙を決め込んでいますが、

There seems to be a lot of fuss about "moe characters" these days -- but I don't want to get involved in anything strange, so I'll keep quiet.

「そこに、創作者に対する敬意はあるのか」と思うことはあります。

However, I often wonder "Is there any respect for the creator there?

2021/11,江端さんの技術メモ

wg.Add():   wg.Add(n)でn個の並行処理が存在することを伝え

wg.Done(): wg.Done()で終了を伝える

wg.Wait():wg.Wait()で並行処理が終わるまで(wg.Done()で終了を伝えるまで)処理をやめない

2021/11,江端さんの技術メモ

=======================

https://github.com/SierraSoftworks/multicast

マルチキャストでは、チャンネルをリスナーのリンクリストとして実装しています。リスナーは、受信したメッセージを次のリスナーに自動的に転送してから、自分のCチャンネルで公開します。

このアプローチにより、チャネルに属するリスナーの配列を維持する必要がなくなり、実装が大幅に簡素化されます。

=======================

以下は、readme.mdに記載されているプログラムを、ちょっとだけ改造したもの(syncを加えた)

package main

import (
	"fmt"
	"sync"

	"github.com/SierraSoftworks/multicast"
)

func main() {
	c := multicast.New()
	wg := sync.WaitGroup{}

	wg.Add(2)

	go func() {
		l := c.Listen()
		wg.Done()
		defer wg.Done()
		for msg := range l.C {
			fmt.Printf("Listener 1: %s\n", msg)
		}
		fmt.Println("Listener 1 Closed")
	}()

	go func() {
		l := c.Listen()
		wg.Done()
		defer wg.Done()
		for msg := range l.C {
			fmt.Printf("Listener 2: %s\n", msg)
		}
		fmt.Println("Listener 2 Closed")
	}()

	wg.Wait()
	wg.Add(2)

	c.C <- "1 Hello World!"
	c.C <- "2 Hello World!"
	c.C <- "3 Hello World!"
	c.C <- "4 Hello World!"

	c.Close()

	wg.Wait()
}

 

ebata@DESKTOP-P6KREM0 MINGW64 ~/goga/3-7
$ go run main.go
Listener 1: 1 Hello World!
Listener 1: 2 Hello World!
Listener 2: 1 Hello World!
Listener 2: 2 Hello World!
Listener 2: 3 Hello World!
Listener 2: 4 Hello World!
Listener 2 Closed
Listener 1: 3 Hello World!
Listener 1: 4 Hello World!
Listener 1 Closed

久しぶりに、「世界に感謝を」という気持ちになりました。

https://github.com/SierraSoftworks/multicast/blob/main/channel.goの、コメントに日本語コメント(翻訳)を付けたもの

package multicast

import "sync"

// Channel represents a multicast channel container which provides
// a writable channel C and allows multiple listeners to be connected.
// Channelは、書き込み可能なチャンネルCを提供し、複数のリスナーの接続を可能にする
// マルチキャストチャンネルコンテナを表します。

type Channel struct {
	// C is a writable channel on which you can send messages which will
	// be delivered to all connected listeners.
	// Cは書き込み可能なチャンネルで、接続されているすべてのリスナーに配信される
        // メッセージを送ることができます。

	C chan<- interface{}

	c chan interface{}
	l *Listener
	m sync.Mutex
}

// New creates a new multicast channel container which can have listeners
// connected to it and messages sent via its C channel property.
// このコンテナにはリスナーが接続され、C channelプロパティでメッセージが送信されます。

func New() *Channel {
	c := make(chan interface{})

	return From(c)
}

// From creates a new multicast channel which exposes messages it receives
// on the provided channel to all connected listeners.
// Fromは、新しいマルチキャストチャネルを作成し、提供されたチャネルで受信した
// メッセージを、接続されているすべてのリスナーに公開します。

func From(c chan interface{}) *Channel {
	return &Channel{
		C: c,
		c: c,
	}
}

// Listen returns a new listener instance attached to this channel.
// Each listener will receive a single instance of each message sent
// to the channel.
// Listenは、このチャンネルに接続された新しいリスナーのインスタンスを返します。
//各リスナーは、チャンネルに送信された各メッセージのインスタンスを1つずつ受信します。

func (c *Channel) Listen() *Listener {
	c.m.Lock()
	defer c.m.Unlock()

	if c.l == nil {
		c.l = NewListener(c.c)
	} else {
		c.l = c.l.Chain()
	}

	return c.l
}

// Close is a convenience function for closing the top level channel.
// You may also close the channel directly by using `close(c.C)`.
// Closeは、トップレベルのチャンネルを閉じるための便利な関数です。
// close(c.C)`を使ってチャンネルを直接閉じることもできます。

func (c *Channel) Close() {
	c.m.Lock()
	defer c.m.Unlock()

	close(c.c)
}

 

https://github.com/SierraSoftworks/multicast/blob/main/listener.goの、コメントに日本語コメント(翻訳)を付けたもの

package multicast

// Listener represents a listener which will receive messages
// from a channel.
// リスナーは、チャンネルからのメッセージを受信するリスナーを表します。
type Listener struct {
	C <-chan interface{}
	f chan interface{}
}

// NewListener creates a new listener which will forward messages
// it receives on its f channel before exposing them on its C
// channel.
// NewListenerは、Cチャンネルで公開する前に、fチャンネルで受信したメッセージを
// 転送する新しいリスナーを作成します。

// You will very rarely need to use this method directly in your
// applications, prefer using From instead.
// アプリケーションでこのメソッドを直接使用することはほとんどないと思いますが、
// 代わりにFromを使用してください。

func NewListener(source <-chan interface{}) *Listener {
	out := make(chan interface{}, 0)
	l := &Listener{
		C: out,
	}

	go func() {
		for v := range source {
			if l.f != nil {
				l.f <- v
			}
			out <- v
		}

		if l.f != nil {
			close(l.f)
		}
		close(out)
	}()

	return l
}

// Chain is a shortcut which updates an existing listener to forward
// to a new listener and then returns the new listener.
// Chainは、既存のリスナーを更新して新しいリスナーに転送し、
// その新しいリスナーを返すショートカットです。

// You will generally not need to make use of this method in your
// applications.
// 一般的には、このメソッドを使用する必要はありません。

func (l *Listener) Chain() *Listener {
	f := make(chan interface{})
	l.f = f
	return NewListener(f)
}

 

package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/SierraSoftworks/multicast"
)

func bus_func(i int, wg *sync.WaitGroup, ch *multicast.Channel) {

	l := ch.Listen()
	wg.Done()
	defer wg.Done()

	/*
		// これだといいんだけど、多面待ちができない
		for msg := range l.C {
			fmt.Printf("Listener %d: %s\n", i, msg)
		}

	*/

	for {
		select {
		case v := <-l.C:
			if v == nil {
				return
			}
			fmt.Println(i, v)
		}
		//time.Sleep(1 * time.Second)
	}

	//fmt.Printf("Listener %d Closed\n", i)
}

func main() {
	c := multicast.New()
	wg := sync.WaitGroup{}

	/*
		wg.Add(2)
		go func() {
			l := c.Listen()
			wg.Done()
			defer wg.Done()
			for msg := range l.C {
				fmt.Printf("Listener 1: %s\n", msg)
			}
			fmt.Println("Listener 1 Closed")
		}()

		go func() {
			l := c.Listen()
			wg.Done()
			defer wg.Done()
			for msg := range l.C {
				fmt.Printf("Listener 2: %s\n", msg)
			}
			fmt.Println("Listener 2 Closed")
		}()
	*/

	for i := 0; i < 3; i++ {
		wg.Add(1)
		go bus_func(i, &wg, c)
	}

	wg.Wait()
	wg.Add(2)

	c.C <- "1 Hello World!"
	time.Sleep(time.Second)

	c.C <- "2 Hello World!"
	time.Sleep(time.Second)

	c.C <- "3 Hello World!"
	time.Sleep(time.Second)
	c.C <- "4 Hello World!"

	c.Close()

	wg.Wait()
}

 

package main

import (
	"fmt"
	"sync"
	"time"

	"github.com/SierraSoftworks/multicast"
)

func bus_func(i int, wg *sync.WaitGroup, ch *multicast.Channel) {

	l := ch.Listen()
	wg.Done()
	defer wg.Done()

	/*
		// これだといいんだけど、多面待ちができない
		for msg := range l.C {
			fmt.Printf("Listener %d: %s\n", i, msg)
		}

	*/

	tick := time.Tick(time.Millisecond * 10000)

	for {
		select {
		case v := <-l.C:
			if v == nil { // c.Close() で goroutineをクローズする
				return
			}
			fmt.Println(i, v)

		case t := <-tick:
			// ここに送信するものを入れる
			fmt.Println("tiched", t)
		}

		//time.Sleep(1 * time.Second)
	}

	//fmt.Printf("Listener %d Closed\n", i)
}


func main() {
	c := multicast.New()
	wg := sync.WaitGroup{}

	/*
		wg.Add(2)
		go func() {
			l := c.Listen()
			wg.Done()
			defer wg.Done()
			for msg := range l.C {
				fmt.Printf("Listener 1: %s\n", msg)
			}
			fmt.Println("Listener 1 Closed")
		}()

		go func() {
			l := c.Listen()
			wg.Done()
			defer wg.Done()
			for msg := range l.C {
				fmt.Printf("Listener 2: %s\n", msg)
			}
			fmt.Println("Listener 2 Closed")
		}()
	*/

	for i := 0; i < 5; i++ { // ここの"5"は  (Aに飛ぶ)
		wg.Add(1)
		go bus_func(i, &wg, c)
	}

	wg.Wait()

	wg.Add(5) // (Aから)ここの"5"と一致している必要がある(が理由が分からん)

	c.C <- "11111!"
	//time.Sleep(time.Second)

	c.C <- "22222!"
	//time.Sleep(time.Second)

	c.C <- "33333!"
	//time.Sleep(time.Second)

	c.C <- "44444!"
	//time.Sleep(3 * time.Second)

	c.Close() // これでスレッドを全部止める

	wg.Wait()
}