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

readme

readme

C:\Users\ebata\goga\3-23に格納されている(絶対忘れると思ったので、アップしておく)

対向サーバは、〜/go_template/tests/server23.go

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

【Golang】structのField名で気をつけるところ

「小文字で始まるField名は外部パッケージからのアクセスできない」 って、どんな言語仕様なんだ・・・

いや、privateとかpublicなんぞ使うよりずっといいって思うよ。

でも、こんなことでvscodeから怒られているとは思わなかったよ。

 

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

みなさん。 golang の ":="は、変数宣言せずに変数を使える便利な奴ですが、スコープ(有効範囲)を間違えて、二重使用すると「地獄」を見ますよ。

/////a_Point := liPoint
	a_Point := liPoint

	for {
		/////b_Point := a_Point // aがスタート、bがゴール
		b_Point := a_Point // 現在のゴールをスタートにする

		a := <-ch3 // センタからch3待ち(ゴールを教えてもらう)
		if a != -1 {
			a_Point = li[a.(int)]

この最後の行を、

a_Point := li[a.(int)]

となっていて、訳の分からない変数の追跡で、数時間失いました。

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

以前、こちらの日記に、

―― VR(Virtual Reality)のエロが凄い

という内容を掲載しました。

あの時は、会社での飲み会だったので、あまり詳しい話が聞けませんでした。

この度、私のコラムをご愛読して頂いている読者のMさんより(EE Times JapanのMさん(Ms.M)とは別の方)、詳細なレポートを頂きました。

VRを理解する上で、優れたコンテンツと思いましたので、Mさんの許諾を得て、以下に公開させて頂きます。

====== ここから =====

VRの最大の特徴は「人は視覚と聴覚を仮想されると、それを現実として認識する」です。

VRとの出会いはゲームでした。

独身一人暮らし時代、VRでバイオハザードという一人称視点のホラーゲームをプレイしていました。

プレイ中にムービーがあったんですが、その内容は

「自分が椅子に拘束され、両手首も前手で拘束された状態から、チェーンソーで両手首を切断される」

というものでした。

(自分自身もソファに座って、コントローラーを持っていたので、ムービーと全く同じ体制を取っていました)

仮想現実の自分が、両手首を切断されたとき、いの一番に自分は叫びました。

「痛ッッたくない!!!」

-----

VRでをしばらく装着すると、「ここが仮想現実である」という認識がどんどんなくなって、「仮想現実が現実化」します。

その時チェーンソーで切られた手首は間違いなく自分の手首であり、「痛くない」ことで、これがVRだったことを思い出すほどにです。

また、エースコンバットという戦闘機のフライトシミュレーションゲームのVR版をプレイした時は、ヴァーティゴに陥り、VRがなければ戦闘機パイロットでしか経験できないであろう経験をしました。

VRは現実です。

ゲームプレイ後、VRを外して見える自分の部屋を見て

「なんで俺は(洋館やコックピットでなく)ここにいるんだ?」

と一瞬思うほどには現実です。

-----

そしてVRのAVです。("ここから本論" by 江端)

先述のとおり、「VRをしばらく装着していると仮想現実が現実化」します。

僕はワクワクしながら「紗倉まなのVRAV」を購入し視聴を開始しました。

部屋の中でベッドに仰向けになっていたところ(この瞬間、僕も体勢を「座り」から「仰向け」に変えました)、部屋のドアが開き、紗倉まなが入ってきました。

自分にのしかかり、キスをしてきます。

(その際、相手の唇が少しずれるくらいなら脳が補正してくれます。)

また、立体音声でささやかれるのも、主観視点もあいまって「紗倉まながそこにいる」と錯覚させるものに十分なものでした。

しかし、ついに紗倉まなが自分のズボンを下ろしたとき、その光景のせいで、途端に自分の脳が仮想現実であることを認識してしまいました。

「俺の脚じゃない」

ズボンを脱がされて出て来た(VR上の)自分の脚が、(実際の)自分の脚より細く、一気に仮想現実であることを突きつけられました。

その後パンツを脱がされたあと、もちろんモザイクが入ってましたが、正直、脚の細さで冷静になれていましたので、そこで特にショックはありませんでした。

-----

その後自分がVRAVを購入する際に気をつけていた点は2つです。

・ズボンを脱がされない(主観側がチャックを下ろすのみの露出)

・陰茎が「模型」(男優の陰茎ではなく陰茎の模型であることにより、抽象度が増すことで脳が騙されやすい)

-----

今は妻もいますので、VRAVを利用することは全くなくなりました(VRを装着したまま自慰行為に励む姿を絶対に妻に見られたくない)が、

―― あれは、自分にとって、エロのパラダイムシフトでした。

====== ここまで =====

以上、非常に秀逸なレポートを、ありがとうございました。

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

"goto"を使う ―― とても、感慨深いです。

"goto"追放キャンペーンが発生したのは、私が大学院在学中の頃でしょうか。そして、現在も"goto"に対する差別的扱いは、変っていません。"goto"なんか使ったら、それだけで『無能』扱いされ、仕事の依頼を打ち切られるような空気すらあります。

まあ、"goto"に、そこまで言われるだけの弊害があるのは確かです。特に「可読性は最悪」ですし、放置された変数が、どんな悪さをするか分かったもんではありません。メモリリークは確実で、スレッドとか使っていたら高い確率でクラッシュします。

しかし、私、学生のころ、N-BASICで"goto"使い倒していましたけど、『あれは、あれで便利でした』。

実際、プログラミング初心者には、とても便利なモノでした。初学者には、"goto"で、ラクラクプログラミングを楽しんでもらっていいんじゃないかな、私は思うのです。


ところで、調べてみたら、golangに、"goto"が実装されていました。C/C++にもありました。Pythonにもありました。Javaにもあるみたいですが、動かないようです(?)。

「使うな」と言われている割に、一応準備だけはされているのが、なかなか興味深いです。

ちゃんと動きましたので、書き残しておきます。

// go run main2.go

package main

import (
	"fmt"
	"time"
)

var ch1 chan interface{}
var ch2 chan interface{}

func main() {

	ch1 = make(chan interface{}) // チャネルの初期化
	ch2 = make(chan interface{}) // チャネルの初期化(ここでは使っていない)

	go loop()

	for i := 0; i < 5; i++ {
		time.Sleep(3 * time.Second) // 3秒待つ
		fmt.Println("send")
		ch1 <- i
	}
}

func loop() {

L:
	fmt.Println("先頭からやりなおし")

	for {
		time.Sleep(1 * time.Second) // 1秒待つ
		fmt.Println("loop")

		//チャネルからメッセージの到着を確認する
		select {
		case i := <-ch1:
			fmt.Println("ch1:", i)
			goto L

		case <-ch2:
			fmt.Println("ch2")

		default:
			//fmt.Println("No value")
		}
	}
}

以上

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

GAを使った推論エンジンを、無限ループで回し続けながら(止めないで)、変数の変更やら、パラメータの変更を突っ込みたいんだけど、その「割り込み」方法が思いつきませんでした。たしか select, caseを使ったやり方があって、defaultの使い方がキモだったようなものがあったような気がして、ちょっとテストプログラム書いてみましたところ、動いたみたいなので、メモの残しておきます。

// go run main2.go

package main

import (
	"fmt"
	"time"
)

var ch1 chan interface{}
var ch2 chan interface{}

func main() {

	ch1 = make(chan interface{}) // チャネルの初期化
	ch2 = make(chan interface{}) // チャネルの初期化(ここでは使っていない)

	go loop()

	for i := 0; i < 5; i++ {
		time.Sleep(3 * time.Second) // 3秒待つ
		fmt.Println("send")
		ch1 <- i
	}
}

func loop() {

	for {
		time.Sleep(1 * time.Second) // 1秒待つ
		fmt.Println("loop")

		//チャネルからメッセージの到着を確認する
		select {
		case i := <-ch1:
			fmt.Println("ch1:", i)

		case <-ch2:
			fmt.Println("ch2")

		default:
			//fmt.Println("No value")
		}
	}
}

で、この最後の"default"をコメントアウトすると、selectが無限待ちになってしまう(チャネルからメッセージが飛んでこないとロックしてしまう)ので注意して下さい。
コメントアウトした結果↓

 

# チャネルからイベント入ったら、初期設定のルーチンまで強制的に飛ばしてしまおうと思っているのですが、golangに、"goto"ってあるのかなぁ・・・

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

今、GAのアルゴリズムを使った動的ルーティングのライブラリ化を試みているのですが、Geneに複雑な(というか、面倒くさい)メカニズムを組み込む為に、四苦八苦しています。

これまで私は、「順序交叉」という手法を用いてきたのですが、昨夜(の深夜)この方式では、私のやりことができないことが判明し、現在、一から作り直しています(2ヶ月分がふっとんだ感じがします)。

で、こちらのpythonで遺伝的アルゴリズム(GA)を実装して巡回セールスマン問題(TSP)をとくのページの「実装例: partial_crossover」の部分を参考させて頂いて、golangで表現してみました。

package main

import (
	"fmt"
	"math/rand"
)

func main() {

	//var sliceA = []int{-1, 1, -1, 2, 6, 3, -1, 4, -1, 5}
	//var sliceB = []int{1, -1, 2, 3, -1, 4, -1, 5, 6, -1}

	var sliceA = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
	var sliceB = []int{1, 3, 5, 7, 9, 0, 2, 4, 6, 8}

	fmt.Println("before sliceA:", sliceA)
	fmt.Println("before sliceB:", sliceB)

	sliceA, sliceB = partial_crossover(sliceA, sliceB)

	fmt.Println("After sliceA:", sliceA)
	fmt.Println("After sliceB:", sliceB)

}

// 交叉:2つの遺伝子をランダムな位置で交叉させる
// def partial_crossover(parent1, parent2):
func partial_crossover(sliceA []int, sliceB []int) ([]int, []int) {

	//num = len(parent1)
	length := len(sliceA)

	//cross_point = random.randrange(1, num-1)
	cross_point := rand.Intn(length-2) + 1

	//cross_point = 3

	fmt.Println("length:", length, "cross_point", cross_point)

	//child1 = parent1
	sliceA1 := make([]int, length)
	copy(sliceA1, sliceA)

	//child2 = parent2
	sliceB1 := make([]int, length)
	copy(sliceB1, sliceB)

	//for i in range(num - cross_point):
	for i := 0; i < length-cross_point; i++ {
		//target_index = cross_point + i
		target_index := cross_point + 1

		//target_value1 = parent1[target_index]
		//target_value2 = parent2[target_index]
		target_value1 := sliceA[target_index]
		target_value2 := sliceB[target_index]

		//exchange_index1 = np.where(parent1 == target_value2)
		//exchange_index2 = np.where(parent2 == target_value1)

		var exchange_index1, exchange_index2 int

		for k := 0; k < length-cross_point; k++ {
			if target_value2 == sliceA[k] {
				exchange_index1 = k
				break
			}
		}

		for k := 0; k < length-cross_point; k++ {
			if target_value1 == sliceB[k] {
				exchange_index2 = k
				break
			}
		}

		//child1[target_index] = target_value2
		//child2[target_index] = target_value1
		//child1[exchange_index1] = target_value1
		//child2[exchange_index2] = target_value2

		sliceA1[target_index] = target_value2
		sliceB1[target_index] = target_value1
		sliceA1[exchange_index1] = target_value1
		sliceB1[exchange_index2] = target_value2
	}
	return sliceA1, sliceB1
}

このコーディングで正解なのか分かりません(私が、バグを仕込んでいる可能性大)。

また検証した結果、私の考えている遺伝子配列(染色体の中に、遺伝子"*"を使う)では、使えないことが分かりました。

この方式では重複する遺伝子は使えないからです(というか、"*"を使う遺伝子配列は、普通ではない)。

もし利用を予定されている方は、十分に検証されることをお勧めします。

以上

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

ソースコードが長くなってくれば、ソースコードを分割するのは当然ですが、Golangでは、この「当たり前」の情報が全然見つからなくて、本当に困っています。

これまで出てきたエラー一覧

  • build command-line-arguments: cannot find module for path _/C_/Users/....
  • # command-line-arguments
  • repeated module statement

「もう、これだから、新しい言葉を覚えるのは嫌なんだよ」と、何十回目かの泣き言を言っています。C/C++で1000万くらいのスレッドが、サクっと作れれば、別にGolangでなくたって・・・と思うのですが、ないものをねだっても仕方がありません。

こちらの記事(https://leben.mobi/go/configuration_and_package/start-go/)を丸パクリさせて頂きました(ちょっとだけ変えています)。

$ tree
.
├── hello
│   ├── greet.go
│   └── hello.go
└── main.go

てな構造でディレクトリを掘って、ファイルを作ってください。

で、

$ go mod init m   ← "m"でもなんでも、好きな文字列を(ここでは"m"とします)
go: creating new go.mod: module m
go: to add module requirements and sums:
        go mod tidy

下↓が必要はどうかは不明

$ go mod edit -replace=m/hello=../hello

として、

.
├── go.mod

を作ります。

$ more main.go
package main

import (
    "fmt"

    "m/hello"  // ← ここ重要
)

func main() {
    fmt.Println(hello.SayHello()) // パッケージ名 + 最初が大文字の関数
    fmt.Println(hello.Greet())
}
$ more hello/hello.go
package hello // ← ここ重要

func SayHello() string { // 最初は大文字
    return "Hello World!"
}

$ more hello/greet.go
package hello // ← ここ重要

func Greet() string { // 最初は大文字
    return "How are you?"
}

とすると、

$ go run main.go
Hello World!
How are you?

と、ちゃんと、動くようになりました。

来週の私へ(メモ) #後で消す

が、全然消せない。

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

「Microsoft Edgeをアンインストールせよ」の旨の指示がやってきたのですが、通常のアンインストールの方法では、できないように設定されているようです。

調べたら、ここにやりかたが書いてあったので、その通りに実行してみました。

①検索フォームに「cmd」と入力
②「コマンドプロンプト」を右クリックし
③「管理者として実行」しましょう

C:\>cd "Program Files (x86)\Microsoft\Edge\Application"
C:\Program Files (x86)\Microsoft\Edge\Application>dir

そこに出てくる、数字(ここでは、98.0.1108.50)を捜して下さい

C:\Program Files (x86)\Microsoft\Edge\Application>cd 98.0.1108.50
C:\Program Files (x86)\Microsoft\Edge\Application\98.0.1108.50>cd Installe

として、ここから、このコマンドを入力します。

setup --uninstall --force-uninstall --system-level

アンインストールの画面が、以下のようになっていれば成功です。

以上