2022/04,江端さんの忘備録

「野心的な目的をもつプロジェクトチームを統率してきたマネージャと」と「目の前のデータを、望むような形で計算することができるプログラマー」

"A manager who has led a project team with ambitious objectives" and "a programmer who can compute the data in front of him/her in any way they wants."

どちらに市場価値があり、どちらの市場規模が大きいのか?

Which has more market value and which has a larger market size?

私は、これまで、ずっと考え続けてきました。

I have been thinking about this for a long time.

-----

内館牧子さんの小説『終わった人』は、私の世代における最大級の『ホラー小説』です。

Makiko Uchidate's novel, "The Finished Man," is one of the greatest "horror novels" of my generation.

―― 日本最高学府の学歴や、一流会社のハイキャリアが、定年後の再就職の最大の障害になる

"Academic background from Japan's highest academic institution and a high career at a prestigious company become the biggest obstacles to re-entering the workforce after retirement"

という話が、登場します。

The story appears in the book.

この小説の主人公だって、『どんな仕事でもやります』と言っているのに、中小企業の会社の社長は、ことごとく採用を躊躇します。

Even the protagonist of this novel says, 'I'll do any job,' but the president of the small business firm hesitates to hire him at every turn.

その気持ち、とても理解できます。

I understand their feeling very well.

だって、社長としては、会社の経営に口を出されたら、嫌ですよね。

Even they would not like to be told how to run their companies.

しかし、再就職を希望するシニアは、会社の経営に口を出すつもりはなく、言われたことをやると思います。

However, I believe that seniors who want to be rehired will do what they are told, with no intention of meddling in the management of the company.

しかし、現場が忖度をしてしまうのです。

However, the people on the field make the conjecture.

これは『逆差別』―― ではなくて、『エリート差別』?

Is this "reverse discrimination" or "elite discrimination"?

-----

私が中小企業の社長であれば、どんなシニアが欲しいか? と考えると、

If I were the president of a small business, what kind of senior would I want?

■新人のように謙虚で、元気で、ちょっと弾けているところもあるけど、

- humble, energetic, and even a little bouncy in some ways, like a rookie.

■注意すれば直ぐに方向転換をし、あまり目立たずに、金に繋がる成果を上げても、それを吹聴しないで、淡々として、

- Change direction quickly if someone pay attention to them, and if achieve something that leads to money without being too obvious, don't blow it out of the water, just go about it nonchalantly, and don't even try to get you to pay attention.

■分からないことがあれば黙って勉強し、それでも分からなければ、若者に素直に頭を下げて教えを請うことができて、

- Study it quietly, and if don't understand, honestly bow down to the young man and ask him to help.

■メンタルでもフィジカルでも、ロバストな

- Robust, both mental and physical.

そんな「シニア」なら、欲しいと思います。

I would want such "seniors".

これからは、新人もシニアも『即戦力』で計られる時代であり、私たちシニアに求められているロールモデルは、

In the future, both newcomers and seniors will be measured by their "readiness to work," and we seniors are expected to be role models, like

『清濁併せ呑むことのできる、老獪な新人』

Newcomers who are required to be broadminded enough to associate with people of all sorts for the sake of working out a compromise.

だと思うのです。

I think.

-----

「野心的な目的をもつプロジェクトチームを統率してきたマネージャと」と「目の前のデータを、望むような形で計算することができるプログラマー」

"A manager who has led a project team with ambitious objectives" and "a programmer who can compute the data in front of him/her in any way they wants."

どちらに市場価値があり、どちらの市場規模が大きいのか?

Which has more market value and which has a larger market size?

市場価値については、私は分かりません。

I do not know about market value.

しかし、市場規模が大きいのは、『命じられた業務を、サクっとやりとげるシニア』だと思うのです。

However, I think the largest market is for "seniors who can quickly complete tasks that are assigned to them.

2020/08,江端さんの技術メモ

https://github.com/gorilla/websocket/tree/master/examples/echo

この"server.go"は、client.goからの通信だけではなく、ブラウザの画面も提供します(スゴい!)。

というか、Goプログラムの中に、html書けるなんて知らんかった。

 
// server.go

// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build ignore
// +build ignore

package main

import (
	"flag"
	"html/template"
	"log"
	"net/http"

	"github.com/gorilla/websocket"
)

var addr = flag.String("addr", "localhost:8080", "http service address")

var upgrader = websocket.Upgrader{} // use default options

func echo(w http.ResponseWriter, r *http.Request) {
	c, err := upgrader.Upgrade(w, r, nil)
	if err != nil {
		log.Print("upgrade:", err)
		return
	}
	defer c.Close()
	for {
		mt, message, err := c.ReadMessage()
		if err != nil {
			log.Println("read:", err)
			break
		}
		log.Printf("recv: %s", message)
		err = c.WriteMessage(mt, message)
		if err != nil {
			log.Println("write:", err)
			break
		}
	}
}

func home(w http.ResponseWriter, r *http.Request) {
	homeTemplate.Execute(w, "ws://"+r.Host+"/echo")
}

func main() {
	flag.Parse()
	log.SetFlags(0)
	http.HandleFunc("/echo", echo)
	http.HandleFunc("/", home)
	log.Fatal(http.ListenAndServe(*addr, nil))
}

var homeTemplate = template.Must(template.New("").Parse(`
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script>  
window.addEventListener("load", function(evt) {

    var output = document.getElementById("output");
    var input = document.getElementById("input");
    var ws;

    var print = function(message) {
        var d = document.createElement("div");
        d.textContent = message;
        output.appendChild(d);
        output.scroll(0, output.scrollHeight);
    };

    document.getElementById("open").onclick = function(evt) {
        if (ws) {
            return false;
        }
        ws = new WebSocket("{{.}}");
        ws.onopen = function(evt) {
            print("OPEN");
        }
        ws.onclose = function(evt) {
            print("CLOSE");
            ws = null;
        }
        ws.onmessage = function(evt) {
            print("RESPONSE: " + evt.data);
        }
        ws.onerror = function(evt) {
            print("ERROR: " + evt.data);
        }
        return false;
    };

    document.getElementById("send").onclick = function(evt) {
        if (!ws) {
            return false;
        }
        print("SEND: " + input.value);
        ws.send(input.value);
        return false;
    };

    document.getElementById("close").onclick = function(evt) {
        if (!ws) {
            return false;
        }
        ws.close();
        return false;
    };

});
</script>
</head>
<body>
<table>
<tr><td valign="top" width="50%">
<p>Click "Open" to create a connection to the server, 
"Send" to send a message to the server and "Close" to close the connection. 
You can change the message and send multiple times.
<p>
<form>
<button id="open">Open</button>
<button id="close">Close</button>
<p><input id="input" type="text" value="Hello world!">
<button id="send">Send</button>
</form>
</td><td valign="top" width="50%">
<div id="output" style="max-height: 70vh;overflow-y: scroll;"></div>
</td></tr></table>
</body>
</html>
`))
// client.go

// Copyright 2015 The Gorilla WebSocket Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build ignore
// +build ignore

package main

import (
	"flag"
	"log"
	"net/url"
	"os"
	"os/signal"
	"time"

	"github.com/gorilla/websocket"
)

var addr = flag.String("addr", "localhost:8080", "http service address")

func main() {
	flag.Parse()
	log.SetFlags(0)

	interrupt := make(chan os.Signal, 1)
	signal.Notify(interrupt, os.Interrupt)

	u := url.URL{Scheme: "ws", Host: *addr, Path: "/echo"}
	log.Printf("connecting to %s", u.String())

	c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
	if err != nil {
		log.Fatal("dial:", err)
	}
	defer c.Close()

	done := make(chan struct{})

	go func() {
		defer close(done)
		for {
			_, message, err := c.ReadMessage()
			if err != nil {
				log.Println("read:", err)
				return
			}
			log.Printf("recv: %s", message)
		}
	}()

	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()

	for {
		select {
		case <-done:
			return
		case t := <-ticker.C:
			err := c.WriteMessage(websocket.TextMessage, []byte(t.String()))
			if err != nil {
				log.Println("write:", err)
				return
			}
		case <-interrupt:
			log.Println("interrupt")

			// Cleanly close the connection by sending a close message and then
			// waiting (with timeout) for the server to close the connection.
			err := c.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
			if err != nil {
				log.Println("write close:", err)
				return
			}
			select {
			case <-done:
			case <-time.After(time.Second):
			}
			return
		}
	}
}

2022/04,江端さんの技術メモ

leafletの地図上に、マウスでクリックするとマーカーが出てきて、マーカーをクリックするとマーカーが消える、というJavaScript

var map = L.map("map", {
        attributionControl: false,
        zoomControl: false
        }).setView(new L.LatLng(35.654543, 139.795534), 18);
        // }).setView(new L.LatLng(35.598563, 139.475528), 18); 広袴

        L.tileLayer('https://{s}.tile.osm.org/{z}/{x}/{y}.png', {
         detectRetina: true,
         maxNativeZoom: 18
        }).addTo(map);

        var leafletView = new PruneClusterForLeaflet(1,1);  // (120,20)がデフォルト

        //地図のclickイベントでonMapClick関数を呼び出し
        map.on('click', onMapClick)
        
        function onMapClick(e) {
            //地図のclickイベント呼び出される
            //クリック地点の座標にマーカーを追加、マーカーのclickイベントでonMarkerClick関数を呼び出し
            var mk = L.marker(e.latlng).on('click', onMarkerClick).addTo(map);
            console.log("click:",e.latlng)
        }

        function onMarkerClick(e) {
            //マーカーのclickイベント呼び出される
            //クリックされたマーカーを地図のレイヤから削除する
            map.removeLayer(e.target);
            console.log("remove:",e.target)
        }

2022/04,江端さんの忘備録

先日、ヨーロッパにある店舗に発注手続をして、送金しようとクレジットカードを使おうとしたら、エラーで弾かれ続けて困りました。

The other day, when I tried to use my credit card to send money to a store in Europe after completing the order process, I was troubled by the fact that it kept getting rejected with errors.

店舗の居所は公開されていなかったのですが、もしかしたら、例の『世界中から金融制裁を受けているあの国』だっかもしれません。

The location of the store was not disclosed, but it might have been "that country that is under financial sanctions from all over the world".

「ビットコインでの支払いもできる」と書いてあったので、こちらで試みようとしました。

It said, "You can also pay in Bitcoin," so I attempted the method.

以前、テスト用に5000円程度購入したお金が、まだいくらか残っていたので。

I still had some money left over from a previous purchase of about $5,000 for testing.

ところが、システムから『残金が足りない』と言われました。

However, the system told me, 'The balance is not enough.

変だなー、と思って調べてみたところ、『送金コストが、購入物の値段より高い』ということが分かり、ビックリしました。

I thought this was strange, so I looked into it and was surprised to find that "the cost of remittance was higher than the price of the purchased item.

『ビットコインは送金コストが安い』が、最大のウリだったと思っていたので。

I thought 'Bitcoin has low remittance costs' was the biggest selling point.

もっとも、これは、ビットコインが理由ではなく、取扱い店舗の手数料かもしれませんが、ともあれ、ビットコインの送金もあきらめて、この取引を取り止めました。

This may not have been because of the bitcoin, but because of the fees charged by the store. Anyway, I gave up on the bitcoin transfer and canceled this transaction.

-----

(1)クレジットカードの使用を停止されると、小売店舗なんぞは簡単に干上がりそう

(1) If retail stores are force to stop using credit cards, they are going to dry up easily.

(2)ビットコインは、決済手続の抜け道として、使えそう

(2) Bitcoin could be used as a loophole in payment procedures.

という、現在、ニュースで報道されていることを、実体験することができました。

This was a real experience of what is currently being reported in the news.

-----

先程、お世話になった方に、Amazonギフトを使って御礼を送付しました。

I just sent "a thank you" to the person who helped me with an Amazon gift.

手続30秒でした。

The procedure took 30 seconds.

『本当に、ラクだなぁ』

"It's really, really easy."

と実感しています。

I realize that.

2022/04,江端さんの忘備録

プログラムのバグというのは、本当にささいなものです。

A bug in a program is really a small thing.

カリフォルニアの1/3を大停電を発生させた原因のバグが、「たった3行のプログラム」であったことは有名ですが、私は驚きません。

I am not surprised that the bug responsible for causing a major blackout in 1/3 of California was famously "just three lines of programming".

というのは、私は3日間ぶっつづけで、3つのプログラムのトレースを100回以上チェックして、データの読み込みタイミングのズレを見つけて、

Because I spent three days straight checking the traces of three programs over a hundred times to find the timing discrepancies in reading the data, and

―― JavaScriptの1行をコメントアウトしただけで、プログラムはあっさりと動き出しました。

"I commented out one line of JavaScript and the program started working easily."

「PrumeMobileのサーバ化」もどきの実装に目処が立ちました

で、残っているものは、山のようにつけ加えた(全く関係のなかった)変数や、膨大なプリントアウトメッセージが書き込まれている、とても汚ない不様なプログラムリストです。

So, what is left is a very dirty, ugly program list with a mountain of added (and totally unrelated) variables and a huge number of printout messages written on it.

これから、これを、未来の私が読める程度に、キレイにしてサーバにアップするという、あまり楽しくない作業が残っています。

Now I have the not-so-fun task of cleaning it up and uploading it to the server so that future for me.

-----

文部科学省のプログラミング教育というのは、このような、プログラム開発の現状を無視しています。

Programming education by the Ministry of Education, Culture, Sports, Science and Technology (MEXT) ignores this current state of program development.

そして、「プログラム的思考」なるものを教えることができる、と、思っているようです。

And they seem to think that they can teach something that is "programmatic thinking".

ただ、文部科学省としては、『それしか、やりようがない』というのは、私にも理解できます。

However, I understand that the Ministry of Education, Culture, Sports, Science and Technology says, 'That's the only way to do it'.

もし、プログラム開発のフロント現場のリアルを、子どもたちに強いたりしたら、全員が逃げだすことを、私は受けあいます。

I assure you that if the MEXT force children to experience the realities of the front lines of program development, they will all run away.

だから、

So, I think,

―― まあ、そういうこと(「プログラム的思考」)が本当に実現できれば、子どもと文部科学省の両方に、心の底から『おめでとう』と言える

"Well, if such a thing can really happen, I can say 'congratulations' from the bottom of my heart to both the child and the Ministry of Education"

と思っています。

10年後を楽しみに待つとしましょう。

Let's wait and see what happens in 10 years.

2022/04,江端さんの技術メモ

PrumeMobileのサーバ化

から、1日もあれば、動かせるだろうと思ったのですが、そこから、redisのパブサブ、Golangのmap、JavaScriptの改造、えらい目に会いましたが、ようやく目処が立ちました。

PrumeMobileは、Webのメモリを使うので、単なるWebサーバのようには取り扱えないので、色々工夫をしました。デバッグで苦労しました。

嬉しい気持ちは、直ぐに消えてしまうので、消える前に記録しておきました。

 

2022/04,江端さんの忘備録

本日は、コラムがリリースされた日なので、日記はお休みです。

Today, new my column is released, so I take a day off.

世界を「数字」で回してみよう(69)番外編

「それでもコロナワクチンは怖い」という方と一緒に考えたい、11の臨床課題

Let's turn the world by "Number"(69) Extra:

11 Clinical Issues to Consider about those who "still fear of Corona Vaccine"

-----

今回のメインテーマであるところの、「ワクチン接種への恐怖」について、嫁さんと話をしました。

I talked with my wife about the main theme of this issue: fear of vaccination.

江端:「ワクチン接種を怖いとは思わなかった?」

Ebata: "You didn't find the vaccination scary?"

嫁さん:「持病もないし、副反応の話も聞いていたし、なんとなく『私は大丈夫かな』と」

Wife: "I don't have any pre-existing conditions, and I had heard about the side effects, so I kind of thought, 'I'll be fine.'"

江端:「もし、過去に、強いアレルギー反応とか、アナフィラキシーで、救急搬送とかされていたらどうかな?」

Ebata: "How do you think if you had had a strong allergic reaction or anaphylaxis in the past and you had had to go to the emergency room?"

嫁さん:「それなら、絶対に『怖い』と感じると思う。『何もして欲しくない』と思って当然だと思う」

Wife: "Then I would definitely feel 'scared. ' I think it's natural to feel like, 'I don't want me to do anything.'"

------

私の母は、一回目の接種直後に入院して、その後の接種はドクターストップがかかり、その後も入退院、転院を繰替えしていました。

My mother was hospitalized immediately after the first vaccination, and subsequent vaccinations were stopped by the doctor, and she was in and out of the hospital and transferred to other hospitals repeatedly.

そして、今年の1月に、心停止して死去しました。

Then, in January of this year, she died of cardiac arrest.

もしかしたら、おふくろの死因は、『ワクチン接種』だったのかもしれません。

Perhaps the cause of my mother's death was the 'vaccination'.

だが、それでも、私たちは、自分の命と、他人の命の為に、決断しなければならない ―― 今は、そういう時なのです。

もし、私が心筋炎で突然死するようなことがあれば、『コロナワクチン接種』が原因なのかもしれません。

If I were to die suddenly from myocarditis, it might be due to 'corona vaccination'.

あるいは、毎年受けている『インフルエンザワクチン接種』かもしれませんし、週一くらいで摂取している『精神安定剤』かもしれません。

Or it could be the "flu vaccination" that I receive every year, or the "tranquilizers" that I take once a week.

あるいは一月に一回くらい摂取している『睡眠薬』の可能性もあり、あるいは大穴で『北極ラーメン』が原因になるかもしれません。

Or it could be the "sleeping pills" that I take once a month or so, or it could be "Hokkyoku Ramen".

私は、ふざけた話をしようとしているのではないのです。

By the way, I am not trying to be a joke.

今回のコラムで、シバタ先生も論じていますが、

As Dr. Shivata discusses in this column.

(1)ワクチン接種で心筋炎で死亡している人もいれば、

(1) Some people have died of myocarditis because of vaccination

(2)コロナ感染で心筋炎で死亡している人もいれば、

(2) Some people have died of myocarditis due to COVID-19 .

(3)前記(1)(2)と無関係で心筋炎で死亡している人もいます

(3) Some people have died of myocarditis unrelated to the above (1) and (2)

(その比率については、コラムの『CQラストナンバー』をご一読下さい)。

(Please read the column "CQ Last Number" for more information on that ratio.)

ワクチン接種をすれば、その理由は上記(1)(2)(3)のいずれかを特定することができなくなりますが、ワクチン接種をしなければ、少なくとも(1)について考える必要はなくなります。

If you vaccinate, you will not be able to identify any of the reasons for (1), (2), or (3) above, but if you do not vaccinate, you will not have to consider at least (1).

それはそれで、納得できる死に方の一つだとと思います。

I think that is one of the most satisfying ways to die.

『江端という奴のコラムにそそのかされて、ワクチン接種なんぞをしたせいで、私は死ぬのだ』

"I'm going to die because I was seduced into getting vaccinated by a column by a guy named Ebata"

と思い込んで最期を迎える人生は、絶対に悔いの残る人生になるでしょう。

I am sure that the life that ends with the thought, will be a life of regret.

-----

私は、その逆パターンです。

I am the reverse pattern.

『mRNAワクチン接種の日を、遠足を待つような子どものような気持ちで待っていた』

"I waited for the day of the mRNA vaccination like a child waiting for a field trip"

という人間は ―― 国内に10人もいないだろうと思いますが ―― それでも、いるんです、ここに1人。

I doubt there are 10 such people in the country, but still, here is one.

インシリコ(コンピュータを使った設計等)によるワクチンというだけで、ワクワクしていました。

I was excited just by the idea of vaccines by in silico (computer-aided design, etc.).

我が国はコロナワクチン後発組である上に、国内でも医療従事者の次の順番である、という幸運で『バグ出しは完璧』と思っていました。

I thought 'bug out was perfect' with the good fortune that our country is a latecomer to the corona vaccine and is also the next in line of medical professionals in the country.

私たちのフィールドで20年近くも言われてきたフレーズに『アナログとデジタルの融合』がありますが、まさか、こんな形で実現されるとは思いませんでした。

A phrase that has been used in our field for nearly 20 years is "the fusion of analog and digital," but I never thought it would be realized in this way.

それ故、私にとって、『アナログとデジタルの融合は、時期尚早だったか』と思いながら最期を迎える人生は、納得できるものなのです。

Therefore, for me, it is satisfying to end my life thinking, "Was the fusion of analog and digital technology premature?"

-----

よく分かっています ―― 私が、規格外のパラダイムを持っている、ということは。

I am well aware -- that I have an abnormal paradigm.

2022/04,未分類,江端さんの技術メモ

  1. golang内でredis経由でJSONを飛す時
    // パブリッシュ側
    
    type GetLoc struct {
        ID    int     `json:"id"`
        Lat   float64 `json:"lat"`
        Lng   float64 `json:"lng"`
        TYPE  string  `json:"type"` // "PERSON","BUS","CONTROL
        POPUP int     `json:"popup"`
        //Address string  `json:"address"`
    }
    
    		gl.TYPE = "BUS"
    		gl.Lat = 35.654543 + (rand.Float64()-0.5)*0.00001*20
    		gl.Lng = 139.795534 + (rand.Float64()-0.5)*0.00002*20
    		gl.ID = rand.Int() % 5
    
    		json_gl, _ := json.Marshal(gl)
    		r, err := redis.Int(conn.Do("PUBLISH", "channel_1", json_gl))
    
    // サブスクライブ側
    
    	for {
    		switch v := psc.Receive().(type) {
    		case redis.Message:
    			fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
    
    			var gl GetLoc
    			_ = json.Unmarshal(v.Data, &gl)
    			fmt.Println(gl.ID)
  2. golangから直接JavaScriptへJSONを飛す時
    golangから (上記の続き)

    var gl GetLoc
    			_ = json.Unmarshal(v.Data, &gl)
    			fmt.Println(gl.ID)
    
    			//conn.WriteJSON(v.Data)
    			conn.WriteJSON(gl)

    JavaScriptで受けとる

    <script>
            function obj(id, lat, lng, type, popup){
                this.id = id;
                this.lat = lat;
                this.lng = lng;
                this.type = type;
                this.popup = popup;
            }
    
    
            //ws.onmessage = e => console.log(e.data)
            ws.onmessage = function(event) {  // 受信したメッセージはここに飛んでくる
                console.log("RESPONSE",event.data)
                var obj = JSON.parse(event.data);
                console.log("after parse:",obj.id)
            }

ポイントは、Marshal、Unmarshal、parseの使い方

2022/04,江端さんの技術メモ

入力2、出力1のマップを取扱いたい場合のケースを調べてみました。

Golangは、2次元マップの取扱いは簡単なのですが、N次元は、かなり複雑になるようです。調べたところ、以下のような取扱いができることが分かりました。

package main

import "fmt"

func main() {

	// 2次元マップ
	m := map[string]int{}
	//m := make(map[string]int)

	m["apple"] = 150
	m["banana"] = 200
	m["lemon"] = 300

	fmt.Println("0:", m["apple"])

	// 多次元mapは、2次元マップのように簡単には使えない
	// 比較的面倒のないやり方は、以下のように構造体を使う方法(らしい)
	// https://qiita.com/ruiu/items/476f65e7cec07fd3d4d7

	type key struct {
		id  int
		att string
	}

	// 配列宣言
	m1 := make(map[key]int)

	// レコード追加
	m1[key{0, "BUS"}] = 1
	m1[key{0, "PERSON"}] = 1

	m1[key{1, "BUS"}] = 2
	m1[key{1, "PERSON"}] = 11

	// レコードの一つを表示
	fmt.Println("1:", m1[key{1, "BUS"}])
	// レコードの全部を表示
	fmt.Println("2:", m1)

	// 変数を使う方法
	id0 := 1
	att0 := "PERSON"
	fmt.Println("3:", m1[key{id0, att0}])

	// レコードの削除
	delete(m1, key{1, "BUS"})
	fmt.Println("4:", m1)

	for i := range m1 {
		fmt.Println("5:", i)
	}

	// 変数を使って、キーの存在を確認する
	id0 = 1
	att0 = "PERSON"
	value, isThere := m1[key{id0, att0}]
	fmt.Println("6:", value, isThere)

	id0 = 2
	att0 = "PERSON"

	value, isThere = m1[key{id0, att0}]
	fmt.Println("7:", value, isThere)

	// レコード追加の例

	id0 = 3
	att0 = "BUS"
	new_id0 := 20

	fmt.Println("8:", m1)

	_, isThere = m1[key{id0, att0}]
	if !isThere {
		m1[key{id0, att0}] = new_id0
	}

	fmt.Println("9:", m1)

}

出力結果は以下の通りです。

C:\Users\ebata\goga\1-11\test>go run main.go
0: 150
1: 2
2: map[{0 BUS}:1 {0 PERSON}:1 {1 BUS}:2 {1 PERSON}:11]
3: 11
4: map[{0 BUS}:1 {0 PERSON}:1 {1 PERSON}:11]
5: {1 PERSON}
5: {0 BUS}
5: {0 PERSON}
6: 11 true
7: 0 false
8: map[{0 BUS}:1 {0 PERSON}:1 {1 PERSON}:11]
9: map[{0 BUS}:1 {0 PERSON}:1 {1 PERSON}:11 {3 BUS}:20]

以上