去年まではMacで立ち上がらないから、iPadでずっと使っていたけど久々にD.LしてみたらMac(M1)でも動くようになっている。選択の余地が広がるのは良いことです。
版数は、
P.S. (2023.1.30)
いまだbuggy感、プレイの停止ができない!もちろんiPad版では問題ないけども。Intel Macでは起動もしない。
admin
la vie libre
問題というよりも、タイミングがそうだからそうなるよねという話です。
Goのgoroutineでの話で、以下のソースをVScodeで読み込ませるとopenclosureというwarningが出ます。実行結果も期待される値ではなくて、例えば全部40とかになるのですが、なぜか?
それは無名関数に明示的に引数としてvを与えてる訳ではないので、無名関数の中でvの使われる時点(v*2)のv値が使われるからです。具体的には並行処理を起動しても、すぐに各ルーチンが実行される訳でもなくて実行タイミングには遅延があるだろうから、実はvを使おうとしたタイミングではすでにfor range処理が先行したり、あるいは終了している可能性もあるから。
対応方法はv無名関数に引数として渡すのがスマートなやり方になるでしょう。
https://github.com/mushahiroyuki/lgo/blob/main/example/ch10/ex1005.go
package main
import "fmt"
func main() {
a := []int{2, 4, 6, 8, 10, 12, 14, 16, 18, 20} //liststart
ch := make(chan int, len(a))
for _, v := range a {
go func() {
ch <- v * 2
fmt.Println(":", v)
}()
}
for i := 0; i < len(a); i++ {
fmt.Print(<-ch, " ")
} //listend
fmt.Println()
}
こうすれば、無名関数が不規則なタイミングでその時点のv値を使用することなく、意図した値を引き渡すことができます。別の対応方法としてはvをシャドーイング(v := vをfor rangeの直後に挿入)しても良さそうですが。いずれにしろ並行処理の実行順序は保証されないので、結果の並びは昇順にはなりません。
go func(v int) {
ch <- v * 2
fmt.Println(":", v)
}(v)
admin
gobotはrobotics/IoT用のフレームワークですが、サポートモデルとしてTelloが対象に含まれています。
https://gobot.io/blog/2018/04/20/hello-tello-hacking-drones-with-go/
でコマンド制御と動画再生を行っているので、コードを実行してみました。
動画の再生にはmplayer(これは追加インストール必要でした)を使って、goから引き渡しています。
$ brew install mplayer
でインストールします。go getでもmplayerがインストールできますが、外部アプリなのでこちらではない。
<環境構築>
Goはインストール済みの前提で、gobotの他にdji/telloのインストールも必要。これはmod内でしかインストールできません。
% go get -d -u gobot.io/x/gobot/...
% go get gobot.io/x/gobot
% go get gobot.io/x/gobot/platforms/dji/tello
<Telloから画像受け取り再生するコード>
Telloの素のコマンドは意識する必要はなくて関数でwrapされています。明示的に並行処理は使っていなくて、drone.On()はイベント待ちのように見えます。
package main
import (
"fmt"
"os/exec"
"time"
"gobot.io/x/gobot"
"gobot.io/x/gobot/platforms/dji/tello"
)
func main() {
drone := tello.NewDriver("8890")
work := func() {
mplayer := exec.Command("mplayer", "-fps", "25", "-")
mplayerIn, _ := mplayer.StdinPipe()
if err := mplayer.Start(); err != nil {
fmt.Println(err)
return
}
drone.On(tello.ConnectedEvent, func(data interface{}) {
fmt.Println("Connected")
drone.StartVideo()
drone.SetVideoEncoderRate(4)
gobot.Every(100*time.Millisecond, func() {
drone.StartVideo()
})
})
drone.On(tello.VideoFrameEvent, func(data interface{}) {
pkt := data.([]byte)
if _, err := mplayerIn.Write(pkt); err != nil {
fmt.Println(err)
}
})
}
robot := gobot.NewRobot("tello",
[]gobot.Connection{},
[]gobot.Device{drone},
work,
)
robot.Start()
}
動画は外部のアプリを使っているせいか、遅延が大きいのと画素が飛んでいます。gobotの本質とはそれほど関係ないですが、
gobotはこれからも成長していくだろうから、Robotics/IoTアプリ開発はかなり楽になりそうです。
admin
interfaceはGo言語における唯一の抽象型だそうで、抽象型というのは実装の自由度がある訳だから使いこなせば便利でしょう。
ここでは使いこなしではなくて、基本機能の説明です。構造体のデータの操作を行う二つのメソッドを定義しています。
package main
import (
"fmt"
)
type person struct {
FirstName string
FamilyName string
Age int8
}
type inf interface{
print()
exchange()
}
func (p *person) print(){
fmt.Println(p.FirstName, p.FamilyName, p.Age)
}
func (p *person) exchange(){
fn := p.FirstName
p.FirstName = p.FamilyName
p.FamilyName = fn
p.print()
}
func main(){
var i1 inf = &person{
FirstName: "Mary",
FamilyName: "Bloody",
Age: 36,
}
i1.print()
i1.exchange()
}
実行結果は、
Mary Bloody 36
Bloody Mary 36
Goの場合にはJavaやC#のように明示的なimplementは不要です、つまり緩い関係になってます。interfaceで定義したメソッドが全て実装されていればimplementと等価です。
じゃ『interfaceは何が良いの?』というとそれは抽象型だからというところに行き着くでしょう、何故なら実装をどう記述しようがinterfaceに規定したメソッドと同じ形(名称、引数と戻り値)であれば入れ替えできるわけで、実は明示的では無いですが継承や多態性が実現できることになります。それゆえGoにおける唯一の抽象型というのは使い方に多様性があることになります。
例えば、上の例で異なる型を扱う同名のメソッドを定義すれば、それは正しく多態性になる訳だから。
このように型によって緩やかな結合を取ることがGoの一つの大きな特徴であるように思います
P.S. (2023/1/25)
interfaceの型名は~~er(~~するもの)とするのが通例のようですから、命名規則からは外れています。
admin
https://isehara-3lv.sakura.ne.jp/blog/2022/07/18/m1-macbook-air到着/
昨年夏にM1 MacBok Airも立ち上げましたが、Intel Macが継続して必要だった大きな理由のFusion 360が動かない問題は今年の夏頃にはnative対応できるらしい。
以下、Autodeskのサイトからの引用、
唯一の残りはレーザープリンタードライバーが対応しないから使えないだけ、トナー変えてそれほど使っていないから勿体無いし、そもそもプリンタ使う頻度も少ないからどうするか?
P.S. 2023/1/23
canonのサポート見てみたらLBP6230のVentura対応ドライバーが登録されてたのでインストール。特にApple Siliconの記述はないからユニバーサルか。
admin
https://isehara-3lv.sakura.ne.jp/blog/2023/01/17/goは値渡し言語、/
で、Goは値渡しなので、渡し先で値を変更するならポインター渡しと言っていますがその例です。
以下のソースで関数printPersonにポインターを渡した時はjohnの値が変更されていますが、値渡しにすると元の値は変更されません。
package main
import (
"fmt"
)
type Person struct{
LastName string
FirstName string
Age int
}
func (p Person) printPerson(p1 *Person) Person{
p1.Age = 72
fmt.Println("John : ", p1.FirstName, p1.LastName, p1.Age)
return *p1
}
func main() {
var john Person
john.FirstName = "John"
john.LastName = "Wein"
john .Age = 70
john.printPerson(&john)
fmt.Println("returned age : ", john.Age)
}
以下はポインタ渡しと値渡しでの実行結果です、確かに値渡しではオリジナルの情報は更新されません。
<ポインター渡し>
John : John Wein 72
returned age : 72
<値渡し>
John : John Wein 72
returned age : 70
admin
初めてRustをPlaygroungで動かしてみたけど、結構独特だと思う
“for” loopはイテレータ専用
“The for in construct can be used to iterate through an Iterator. “
通常のループ処理は無限ループ使ってcontinueとbreakで条件判断
<初めてのRustのコード>
fn main() {
let mut i = 0;
loop {
println!("i = {}", i);
if i == 10{
break i;
}
i += 1;
};
}
・mutable変数はmutで宣言が必要、宣言しないとimmutable変数になる
・println!では必ずプレースホルダー”{}”を入れる
・loopの}にも;が必要、if{}の}の後ろにはあっても無くてもコンパイルエラーにはならないけれども
・ifの条件をカッコ()で括らないのはGoと同じ
admin
タイトルの通りですがGo言語は値渡し、例えば関数に引き渡す引数は値が引数のアドレスとは違う場所の関数内で使用する変数のアドレスにコピーされて使われます。
これでは都合悪い時もあるだろうから、参照渡しのためにポインターが存在知ると考えれば良いかもしれない。ポインターはC/C++の記法そのままで、
package main
import "fmt"
func main() {
val := 20
pointer := &val
*pointer = 23
fmt.Println("address : ", pointer, "value : ", val)
}
address : 0x14000126008 value : 23
のように使います、しかしGoでポインターを普段使いしたら、変数がmutableになることでコードの見通しが悪くなるから使うのは限定的だろうと思う。Goでは通常の変数はすべてimmutable扱いだから、逆に言えばポインター宣言は明示的なmutable宣言であるということです。
例にあるようなケースでわざわざポインターを使う必要性はないし、こんな使い方はしちゃいけない例です。数少ない例外はインターフェースを受け取るだけだとは『初めてのGo言語』の記載。
admin
普通はM5Stackで表示内容の書き換えするときに、一度表示内容を消去する必要がありますが、それが表示がちらつく原因です。
ちらつき防止のためには、画面表示内容をフルで別のバッファーに用意しておいて、それを押し込めば表示消去時間が存在しないことになるのでちらつきの防止ができます。
以下のサンプルから、
https://craft-gogo.com/m5stack-sprite/
をそのまま実装してみましたが、確かにちらつきは見えなくなります。
画面書き換えの処理時間を見るために、前後で時間を取得して処理時間を見てみましたが、画面の押し込み(pushSprite())の処理時間は実は普通に画面を書き込む時間と変わらず、大体40msぐらい掛かっています。要は表示領域を一度クリアしないからちらつきを感じることなくなっているわけで、決してpushSprite()にして画面描画時間が高速化される訳ではありません。
admin