2019年12月7日

[golang]あきらめてパッチにした

GitHubにあったgolangアプリのリポジトリをforkして改造しようとしていた話の続き。

アプリの本体だけならまだよかったのだが、アプリが使っている別リポジトリのライブラリも改造内容に関わっていて、そっちも変更が必要だ。
go.modで置き換えようとしていたのだが、その置き換えだけのためにライブラリをforkして・・・ということをやっていると、もう私の精神力が持たなかった。

 

というわけで、こうした。

  • 置き換えたいリポジトリたちは、go getではなくgit cloneで$GOPATH/srcの方にcloneする
  • cloneしたファイルを編集する
  • リポジトリごとにgit diff > xxx.patchなどとしてパッチファイルを取得する
  • 差分を取得してpatchにしたり、cloneしてpatchをあてるためのスクリプトを作る
  • 自分のリポジトリを作って、そのスクリプトやパッチだけを管理する

 

cloneするときに、forkしたものをオリジナルと同じディレクトリにするなりシンボリックリンクにするなりでもできそうだけど、自分で間違えてしまいそうな気がするのでね。

 

なんか、なんかよい方法があるんじゃないかと思うのだが、探しきれてないのよねぇ。
こちらの、オリジナルをgo getしてupstreamにforkした方を載せる、というのがgolangでのやり方なのかな。

github でホストされている go アプリを fork して PR する時には、まず go get から始めよう - Qiita
https://qiita.com/t-suwa/items/d384facb79866dc16cad

stackoverflowにも出てた。

Using forked package import in Go - Stack Overflow
https://stackoverflow.com/questions/14323872/using-forked-package-import-in-go

 

パッチでやるときの心配は、操作を間違えて消してしまうんじゃないだろうか、というものだ。
それに、一人でやっているからいいけど、複数人でやるとパッチファイルのマージなんかが起きたときに目も当てられないことになってしまいそうだ。

 

ああ、そうだ、その心配があったな。。。
やっぱりupstream方式にした方が無難か。

2019年11月18日

[golang]githubでforkしてrenameした場合

golangで、よくgithub.comからパッケージを取得して使っている印象がある。
githubといえば、fork。
forkすると、パッケージまでのルートが変わる。
そして、githubではリポジトリの名前を変更することもできる。

その両方をやったとき、元のソースファイルをどう変更するのが良いのだろうか?


例題は、これにしよう。

hiro99ma blog: [golang]久々のgolang (3) - 他のpackage
https://hiro99ma.blogspot.com/2019/11/golanggolang-3-package.html

パッケージでこれを使っている。

https://github.com/hashicorp/logutils

これを、自分のところにforkして、かつリポジトリの名前を変えてみた。

https://github.com/hirokuma/logutilsutils

 

一番簡単なのは、一括置換だろう。
「元からそのパッケージを見ていました」ということになれば、なんの問題も無い。
しかし、その書き換えが大量になるのは苦痛だ。

かといって、symbolic linkなんかでごまかすのも、いかがなものかと考えてしまう。
なんか、卑怯な気がする。

理想は、importだけは書き換え、実装の方にはリポジトリ名の変更を感じさせない、というところか。


エイリアス、というものがあるらしい。

https://qiita.com/taji-taji/items/5a4f17bcf5b819954cc1#%E3%82%A8%E3%82%A4%E3%83%AA%E3%82%A2%E3%82%B9%E6%93%8D%E4%BD%9C

 

import分を書き換えた。

import "github.com/hashicorp/logutils"

↓↓

import logutils "github.com/hirokuma/logutilsutils"

go getかな?

$ go get
go: finding github.com/hirokuma/logutilsutils v1.0.0
go: downloading github.com/hirokuma/logutilsutils v1.0.0
go: extracting github.com/hirokuma/logutilsutils v1.0.0
go: local/helloworld/hel imports
        github.com/hirokuma/logutilsutils: github.com/hirokuma/logutilsutils@v1.0.0: parsing go.mod:
        module declares its path as: github.com/hashicorp/logutils
                 but was required as: github.com/hirokuma/logutilsutils

うーん、logutilsutils/go.modがhashicorpのままだからだろうか?
しかし、書き換えてもダメだ。

いや、ダメとか云々の前に、どこからhirokuma/logutilsutilsをダウンロードしているのだろうか?
v1.0.0が付いているのでgithubからtagを削除したのに、それでもまだpkg/mod/には@v1.0.0が付いているのだ。

 

$GOPATH/pkg/以下は全部削除しているし、$GOPATH以下にhashicorp関係のファイルがないところも確認した。
わからん、何を調べたらいいのか分からん。。。

 

苦し紛れに、local/helloworld/helにあるgo.modを削除するとうまくいった。
うまくいったというか、src/github.com/hirokuma/logutilsutilsを置いていたので、それを使うようになったらしい。
go.modには特に何も書いていなかったのだが、ファイルがあるだけで挙動が変わるのか。
GO111MODULE=onとかしてないから、そういうのも原因かもしれん。

2019年11月17日

[golang]__func__的なものを出力したい

golangの練習で、いろいろ関数を書いている。
関数を呼び出していると何を実行しているのかわかりにくくなってきたので、logを出そうかと考えた。
が、別に関数の名前だけ表示すればいいや、とC/C++のプリプロセッサみたいなものを使って出力させようとした。

 

が、golangにはプリプロセッサのようなものは無いらしい。まあ、わからんでもない。プリプロセッサは強力すぎて訳がわからないことまでできてしまいがちだからなぁ。

スタックトレース的なものはあるので、あちこち参考にしながら私も書いてみた。

01: package dbg
02: 
03: import (
04: 	"fmt"
05: 	"runtime"
06: 	"strings"
07: )
08: 
09: //Trace trace log
10: func Trace() {
11: 	print("", "")
12: }
13: 
14: //Head function header
15: func Head() {
16: 	banner := strings.Repeat("*", 30)
17: 	print("\n\n"+banner+"\n", "\n"+banner)
18: }
19: 
20: func print(head string, tail string) {
21: 	upc, fname, fline, _ := runtime.Caller(2)
22: 	fmt.Printf("%s[%s:%d]%s()%s\n", head, fname, fline, runtime.FuncForPC(upc).Name(), tail)
23: }
  

関数の頭で呼んだときは派手派手にしたかったのでHead()とTrace()にわけた。
まあ、Traceっていっても名前を出すだけなんだけどね。

オーバーライドのようなものは無いみたいで、引数を構造体にしてデフォルト引数を実現するような技が出てきた。今回は使ってないがそういうのもあるということで。

あと、文字列なのでポインタ型で渡した方がいいのかと思ったが、string型はどうなのだろうか?

01: package dbg
02: 
03: import (
04: 	"fmt"
05: 	"runtime"
06: 	"strings"
07: )
08: 
09: var banner = strings.Repeat("*", 30)
10: var head = "\n\n" + banner + "\n"
11: var tail = "\n" + banner
12: 
13: //Trace trace log
14: func Trace() {
15: 	empty := ""
16: 	print(&empty, &empty)
17: }
18: 
19: //Head function header
20: func Head() {
21: 	print(&head, &tail)
22: }
23: 
24: func print(head *string, tail *string) {
25: 	upc, fname, fline, _ := runtime.Caller(2)
26: 	fmt.Printf("%s[%s:%d]%s()%s\n", *head, fname, fline, runtime.FuncForPC(upc).Name(), *tail)
27: }
  
emptyをconstにしようとしたけど失敗。よくわからん。。
スタックに場所を確保する程度の重荷だろうから、もうこのままでいいや。

[golang]久々のgolang (4) - 実行ファイル名

こういう構成でビルドした。
main()はmain.goにある。

image

$ cd $GOPATH/src/main
$ go mod init
$ go build
$ ls
ex.go  go.mod  go.sum  main  main.go

実行ファイル名がmainなのはいただけないな、とディレクトリ名を変更した。

$ rm main
$ cd ..
$ mv main gogoex

image

$ go build
$ ls
ex.go  go.mod  go.sum  main  main.go

あれ、mainのままになっているのはなぜだ?
実行ファイル名はmain()を含んでいるファイルのディレクトリ名になると思っていたのだが。

 

go.modの1行目を見ると、こうなっていた。

module main

これを、変更した。

module gogoex

そしてビルド。

$ rm main
$ go build
$ ls
ex.go  gogoex  go.mod  go.sum  main.go

ディレクトリ名よりもgo.modの方が強いのか!
というよりも、実行ファイル名の決定にgo.modが使われるのか。

 

Go Modulesの説明が長いので、理由を探す気力が湧かなかった。
go getなどで更新されるわけでもないので、わざとそうしているのだろうか?
やらかしそうな気がするので、注意しておこう。

ただ、単にモジュール名として使われるだけなら便利かもしれん。
ディレクトリはmain()が入っているのでmain/にしたい、とか。


と、単純に考えてディレクトリ構成を変更していたのだが、ビルドができなくなった。
直下にはgoファイルを置かず、中でディレクトリを作って分けたいのだが。。。

image

~/Golang/go/src/example$ go build
can't load package: package example: no Go files in /home/xxx/Golang/go/src/example

まあ、ないよね。

 

$ go build ./*

これだとエラーは出ずに終わるのだが、実行ファイルが生成されていないようだ。

 

$ go build ./main/main.go
$ ./main/command-line-arguments
I am masao.

なぜか"command-line-arguments"という実行ファイル名ができる。
そして実行できてしまう。

$ go build -o mmm ./main/main.go
$ ls
ex  main  mmm

gccと同じように-oは使えるようだ。

もしや、go.modの"module"はここで使われるものなのでは?

$ go mod init
$ vi go.mod
(適当にmoduleの名前を変更)
$ go build ./main/main.go
build command-line-arguments: cannot load example/ex: malformed module path "example/ex": missing dot in first path element

moduleの名前を変更しないと、main/command-line-argumentsができるが、変更するとエラーになる。

 

どこかで...という形式を使うのを見たことがある。

$ go install -v ./...
$ ls $GOPATH/bin
main

もしかしたらmain/go.modを置くといいのでは?とやってみたのだが、変わらん。
そもそも、./...とか関係あるのかどうかわからんし。

 

んー、適当じゃダメだな。


go build

https://golang.org/cmd/go/#hdr-Compile_packages_and_dependencies

-oはいいとして、ビルド対象の指定方法を知りたいのだ。
[packages]と書いてあるが、.goファイルのリストでもよいらしい。
-vするとコンパイルしたパッケージの名前が表示されるらしい。

$ go build -v ./main/
go build: build output "main" already exists and is a directory

なるほど、ディレクトリと同じ名前になるから生成できなかったというわけか。
golang-standards/project-layoutというものを見てみると、cmd/の中にアプリ名のディレクトリを作るというのが定番らしい。逆らう理由もないのでそうしてみよう。

image

$ go build -v cmd/gogoex/main.go
$ ls
cmd  ex  main

むう、まだディレクトリ名になってくれないのか・・・。

When compiling a single main package, build writes the resulting executable to an output file named after the first source file ('go build ed.go rx.go' writes 'ed' or 'ed.exe') or the source code directory ('go build unix/sam' writes 'sam' or 'sam.exe').

実行ファイル名は、goのファイル名からとるときとディレクトリ名から取るときがあるのか。

$ go build -v ./cmd/gogoex
example/cmd/gogoex
$ ls
cmd  ex  gogoex

なるほど、これでいいんだ。
最初の./を省略するとフルのパッケージ名として解釈しようとするので、相対パスの要領で"cmd/gogoex"とするとエラーになる。
ここなら、example/cmd/gogoex、と指定すれば良い。

 

go install

https://golang.org/cmd/go/#hdr-Compile_and_install_packages_and_dependencies

go buildは実行ファイルをその場に置いておくが、go buildは$GOPATH/bin/に移動させるようだ。

 

go clean

https://golang.org/cmd/go/#hdr-Remove_object_files_and_cached_files

cleanがよくわからん。
前回などは"go build"としてビルドしていて、それは"go clean"で実行ファイルが削除できていた。
でも、今回のようにパッケージ名を指定すると、どこのファイルも消してくれたように見えない。
"from package source directories"とあるから、$GOPATH/pkg/の方を消すのかな?
この程度のサンプルだとよくわからんな。


まあ、実行ファイル名関係についてはこのくらいでよかろう。
Makefileを使う場合もあるらしいし、また調べることになるだろう。

[golang]久々のgolang (3) - 他のpackage

前回golangのpackageのことを調べていたが、github.comなどのpackageについて調べ忘れていた。

 

例題として何かgit関係のリポジトリから取ってこよう。

https://godoc.org/github.com/hashicorp/logutils

ログ出力だったら、難しくないんじゃなかろうか。

local/helloworld/hel/main.go

01: package main
02: 
03: import "log"
04: import "os"
05: import "local/helloworld/hel/makkey"
06: import "github.com/hashicorp/logutils"
07: 
08: func main() {
09: 	filter := &logutils.LevelFilter{
10: 		Levels:   []logutils.LogLevel{"DEBUG", "WARN", "ERROR"},
11: 		MinLevel: logutils.LogLevel("WARN"),
12: 		Writer:   os.Stderr,
13: 	}
14: 	log.SetOutput(filter)
15: 	log.Print("[WARN]Hello, World!\n")
16: 	makkey.Callme(filter)
17: }
  

local/helloworld/hel/makkey/masao.go

01: package makkey
02: 
03: import "log"
04: import "github.com/hashicorp/logutils"
05: 
06: //Callme masao
07: func Callme(filter *logutils.LevelFilter) {
08: 	log.Print("[ERROR]I'm masao!\n")
09: }
  

 

$ go get -d -u github.com/hashicorp/logutils
$ go run local/helloworld/hel
2019/11/16 23:28:51 [WARN]Hello, World!
2019/11/16 23:28:51 [ERROR]I'm masao!

例を見ながら、なんとなく動かせた。


go getでライブラリをダウンロードしたりインストールしたりするのを見ていたので使ってみたのだが、そもそもどうなんだろうか?
他にもglideやらdepやらでインストールすることがあったのだが、そもそもどれが何なのだろうか?

 

  • glideは非推奨になって、depを使ってほしいらしい(glide v0.13.0)
  • depはgolang v1.9以上らしい
  • go getは依存関係は解決してくれるが、パッケージ管理とは異なりそうな気がする
  • vgoという名前も出てくるが、Go Modulesの前身?

 

わけが分からんぞ!

たぶん、golang v1.13以降で、リポジトリにgo.modがあるなら、GO111MODULE=onなどしなくてもGo Modulesの動作をするんだろうと思う。
では、Go Modulesの動作とは何かというと、おそらく$GOPATH/pkg/mod/の下に依存するソースファイルをダウンロードすることだ(ビルドもするのだろう)。「go getがGOPATH modeとは異なる動作をする」といってるので、そうなのじゃなかろうか。

 

私が見たGo Modulesの使い方は、こんなのだった。

$ GO111MODULE=on go install xxx

これでやってるせいか知らないが、pkg/mod/の中に入ってるものはアクセス権があってsudoしないと削除できなかった。

 

仕事でやろうとしているリポジトリはgo.modがあったし、今はgolang v1.13なのでgo getしてみたものの、pkg/mod/にはダウンロードせず、src/github.com/などにだらだらダウンロードし始めてしまった(途中でプロセスを殺したので、最後までは知らない)。

$ GO111MODULE=on go get -u xxx

とすると、pkg/mod/の下にダウンロードしているようだ。src/の下は何も増えていない。

 

「golang v1.13でもGO111MODULE=autoがデフォルトなのはそのままで、ただし$GOPATH/src/の中にgo.modがあればmodule-aware modeになる」らしい。

module-aware modeというのが、私が思うGo Modulesっぽい動作なのだろう。そしてGO111MODULE=onすると最初からGo Modulesっぽい動作をするので、$GOPATH/src/にはダウンロードされないんだろう。

なので、golang v1.13でGO111MODULEは未設定のまま、メインのソースファイルを編集したいが依存するパッケージはそのまま使いたいのなら、本体はgit cloneなどで$GOPATH/src/以下に取得し、その中でgo installすればいいはずだ。go.modがあるなら$GOPATH/pkg/mod/以下に取得するし、無かったら$GOPATH/src/に取得するだろう。

 

私がめんどくさいと思っているのは、$GOPATH/src以下に取得するときなのだ。github.comだったとして、github.com/aaaa/bbbbというリポジトリを取得したいのだったら、

$ mkdir -p $GOPATH/src/github.com/aaaa
$ cd $GOPATH/src/github.com/aaaa
$ git clone https://github.com/aaaa/bbbb

とかしないといかんじゃないか。git cloneで引数を付けてディレクトリを指定してもいいけど、打ち込む文字数はそんなに変わらんし。それがgo getだとディレクトリの作成までやってくれるので使いたかったのだ。


src/local/helloworld/helにはgo.modがないので、go installとかgo getとかすると$GOPATH/src/以下にgithub.com/hashicorpのリポジトリをダウンロードしてくる。

これをsrc/に起きたくなかったら、go.modを書くのが良いだろう。
手動で書かなくても済みそうな気がするが、自動生成はできるのだろうか?

https://github.com/golang/go/wiki/Modules

できそうだ。

$ cd $GOPATH/src/local/helloworld/hel
$ go mod init local/helloworld/hel
$ go build

go mod initでgo.modができて、go buildすると更新されてgithub.com/hashicorp/logutilsがバージョン付きで追加されていた。logutilsもsrc/の下ではなく、pkg/mod/の下に取得されていた。
local/helloworld/hel/makkeyの方は書かれていなかったので、パスで見分けているのかもしれん。

2019年11月16日

[golang]久々のgolang (2) - package

前回に引き続き、golangの勉強。versionは1.13.4。


まずはpackageというかライブラリというか、そういうやつ。

たぶん、種類としてはgo言語標準、ローカルで実装したもの、他から取得したもの、くらいになるんじゃなかろうか。

 

標準ライブラリ

https://golang.org/pkg/#stdlib

これが標準のものだろう。
下の方にOther packagesがあるが、これはメインのgoには入ってないがプロジェクトの一部ではあるらしい。"net"はstandardにもotherにもあるが、otherはgolang.org/x/net(import "goglang.org/x/net/bpf"など)とのこと。

 

ローカルの実装

JavaやC#のイメージだと、機能単位でpackageを分けて、あわよくば他でも使えるようにするだろう。
ライブラリと同じようなイメージかもしれん。

 

他から取得したもの

よく見るのは、これだ。githubなどで公開されているものを使うのだ。
git getとかで取得できていた気がする。

 

 

標準のやつは"fmt"で試せたことにして、まずはローカルの実装だろう。

image

こんな感じで、masao.goというファイルを作った。

local/helloworld/hel/main.go

01: package main
02: 
03: import "fmt"
04: 
05: func main() {
06: 	fmt.Printf("Hello, World!\n")
07: 	//masao.Callme()
08: 	Callme()
09: }
  

 

local/helloworld/hel/masao.go

01: package main
02: 
03: import "fmt"
04: 
05: //Callme masao
06: func Callme() {
07: 	fmt.Printf("I'm masao!\n")
08: }
  

これは、masaoをmainパッケージに置いたので、動いた。
Cなどと違って、別にincludeみたいなことをしなくて良いのだな。

 

では、masao.goを別パッケージにしたらどうなるかと、masaoというパッケージに変更した。

$ go install local/helloworld/hel
can't load package: package local/helloworld/hel: found packages main (main.go) and masao (masao.go) in /home/xxx/Golang/go/src/local/helloworld/hel

見つからないとかなんとかいう以前に、パッケージにmainとmasaoがあるからダメ、みたいなことを言われた。
Javaだとディレクトリ構成やファイル名がパッケージと関連していたが、golangはどうなんだろうか。

https://golang.org/doc/effective_go.html#package-names
Another convention is that the package name is the base name of its source directory;

ファイル名はいいとして、パッケージ名とディレクトリ構成は関連するのか。
ならば、パッケージ名はmakkeyにしてみよう。

image

local/helloworld/hel/main.go

01: package main
02: 
03: import "fmt"
04: import "local/helloworld/hel/makkey"
05: 
06: func main() {
07: 	fmt.Printf("Hello, World!\n")
08: 	makkey.Callme()
09: }
  

 

local/helloworld/hel/makkey/masao.go

01: package makkey
02: 
03: import "fmt"
04: 
05: //Callme masao
06: func Callme() {
07: 	fmt.Printf("I'm masao!\n")
08: }
  

 

これはコンパイルできたし、実行できた。

$ go install local/helloworld/hel
$ hel
Hello, World!
I'm masao!

 

ファイル名は影響しないようだ。
とはいえ、golangは構造体を使ってclassっぽいものを使えたと思うので、それに合わせることになるだろう。

[golang]久々のgolang (1)

いろいろあって、golangをやらねばならなくなりそうだ。
Pythonはスクリプト言語を覚えたいというモチベーションがあったのだけど、golangは仕事で使えればいいや、という程度だ。

まあ、仕事で使える程度、ってのはかなり高い要求なんだけどね。。。


まず、インストールから。Ubuntu18.04でやる。

これを書いている時点のstableバージョン(なのかな?)は、1.13.4。

https://github.com/golang/go/wiki/Ubuntu

PPAのを使って、apt installした。

$ go version
go version go1.13.4 linux/amd64

よかろう。


以前はGOPATHとかGOROOTとかの環境変数を設定していた気がする。
言語はやってなくてもgolangで作られたアプリはインストールしていたのだが、GOPATHしか設定した記憶が無い。
GOROOTは使わなくなったのだろうか?

GolangのGOPATHやGOROOTについて
https://tech.librastudio.co.jp/entry/index.php/2018/02/20/post-1792/

ほう、そうか。
GOROOTはインストール場所だったのか。aptでも有効だったのだろうか?まあ、もう遅いんだけど。

そして、デフォルトでGOPATH未設定の場合でもパスが自動で決められるらしい。
ただまあ、たくさんライブラリを使うようなアプリだったりすると、$GOPATH/srcの中がゴチャゴチャしてくるし、$GOPATH/binをPATHに追加してしまってよいものか悩むシーンも出てくる。
なので、あれこれ切り分けたいとか、golangあまり使わないのでそのときだけ設定したいとかあるだろうから、私はGOPATHは指定するようにしておこう。
pythonのvenvなんかを使い始めてわかったのだけど、GOPATHも環境を分ける方法の1つと考えて良いだろう。ストレージに余裕がある場合は、なるべく分けるようにしよう。

 

そういうわけで、今回は$HOME/Golangを作って、その中でやる。
こんなのをsourceコマンドで読み込んでおけばいいや。

01: #!/bin/bash
02: 
03: export GOPATH=`pwd`/go
04: export PATH=$PATH:$GOPATH/bin
  

では、helloworldしてみる。

$ cd Golang
$ source config.sh  #↑のスクリプト
$ mkdir -p go/src/hello
$ cd go/src/hello
$ vi main.go

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

package main

import "fmt"

func main() {
    fmt.Printf("Hello, World!\n")
}

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

$ go build
$ ./hello
Hello, World!
$

あれ、goって、$GOPATHの下にbin, pkg, srcができて、実行ファイルはbinにコピーされるんじゃないの?

Go言語の作業ディレクトリをドキュメントに従って作り直してみた
https://qiita.com/ttsuzo/items/45eb4fc269986df9122c

ああ、推奨構成みたいなものがあるのね。そしてgo installするとうまいことやってくれるようだ。

$ go install
$ ls ../../bin
hello

ほう。そしてどうでもいいことだが、go buildしてカレントディレクトリに作られていたhelloは削除されていた。
go installの引数は、カレントディレクトリかsrc/からのパスのようだ。

$ cd ..
$ pwd
/home/xxx/Golang/go/src
$ mkdir -p local/helloworld
$ mv hello local/helloworld/hel
$ go install local/helloworld/hel
$ ls ../bin
hel  hello

実行ファイル名はディレクトリ名がそのままになるのか。そして、名前が変わったとしても前回installしたものはそのまま残る、と。追跡はしていないようだ。

$ rm ../bin/*
$ go install local/helloworld/hel
$ go clean local/helloworld/hel
$ ls ../bin
hel

実行ファイルがカレントディレクトリにあったときはcleanすると削除してくれたのだが、binにあるとだめなのか。
helpで"Clean removes object files from package source directories."と書いているから、srcだけなのだろう。

$ go run local/helloworld/hel
Hello, World!

こうすると、バイナリファイルが残っていないけど実行ができている。
main.goがカレントディレクトリなら引数が不要かと思ったが、それはダメだった。


そろそろ、vscodeを使う。
src/で開くべきかgo/で開くべきか悩ましいが、まずはgoにしておこう。

それで気付いたのだが、Goのインデントはハードタブなのだろうか?
C言語でvscodeを使っているときはスペースだったと思うので、言語によって切り替えられているようだ。
https://golang.org/doc/を検索しても出てこないのだが、ネットではハードタブを使うような記述が出てくる。
スペースに置き換えて gofmt -w main.go するとハードタブになるから、少なくともコマンドとしてはハードタブがデフォルトのようだ。

 

vscodeにGoのextensionを入れたのだが、ツールのインストールを要求するのでOKOKとやってたところ、$HOME/Golang/goのbinやpkgにいろいろインストールし始めた。。。
せっかく仮想環境の一環だ、なんて思ってたのに台無しじゃないか。。。
go.toolsGopathにパスを書くと、そこをvscode用の$GOPATHとして使ってくれそうだ。

 

デバッガは、launch.jsonをデフォルトのまま使うことができた。
"${fileDirname}"になっているので、main.goを開いているならそのままでいいのだろう。しかし腰を据えてやるような状態だとmain.goなんかいちいち開いていられないだろう。
たぶんだが、main.goがあるディレクトリまでのフルパスを書けばよさそうだ。フルパスというのが、/home/から書かないとダメみたい。${workspaceFolder}から書き始めるのはよさそうだ。
これは、私が.bashrcなんかにGOPATHを書いてないとか、binにPATHを通してないとか、まだmain.goしかファイルがないとか、いろいろわかってないことが多いので保留にしておこう。

 

goとは関係ないが、vscodeのexplorerで"OPEN EDITORS"を表示したくない場合は

"explorer.openEditors.visible": 0

を追加すると良いそうだ。
あれがあると、ファイルを開くたびにツリーが下に下がっていくので、毎回隠していたのよねぇ。


デバッグできそうな環境ができたので、次からは言語の本体をやっていこう。
基本的なところだけわかれば、あとは仕事しながら覚えてもいいだろう。

2019年10月23日

FLUKE 101

とうとうマルチメータを買った。
FLUKE 101だ。

image

ハンディサイズとは書いてあったが、本当に小さめだった。
今まで片手でずっしり持つタイプしか見たことがなかったので新鮮だ。
「かわいい」というやつか?

 

操作面はシンプル。
HOLDはいいとして、黄色いボタンは何だろうか。
抵抗レンジの通電ブザーとダイオードの切替と、Hzレンジの表示切替のようだ。

プローブのケーブルが長い。
まあ、短いよりはいいだろう。
あと、保護用のキャップが付いている。私は家でしか使わないけど、持って歩くときは無くさないように注意だな。

 

ダイアルの通り電流は計測できないが、普段は電圧と抵抗値くらいしか測らないので十分だろう。

2019年10月22日

I2Cのその後・・・

あれからどうやってもI2Cがうまくいかない。
ゴチャゴチャとハンダ付けしているのがよくないので、取り付けていたユニバーサル基板から外そう。

 

image

最初はハンダ付けした面から取り外そうとしたのだが、両側からハンダ付けしている場合はほぼ無理なのよね。。。
もしかしたら物理的にハンダを吸い取るタイプの装置があればよかったのかもしれないが、私が持っているのはハンダ吸い取り線だ。
表面は吸い取れても、スルーホールの中までは無理だった。

 

では、と上から吸い取る方式に変更した。
こっちも似たようなものではあるが、ピンが飛び出している距離が短いので、ハンダが溶けている間に基板を引っ剥がせるかもしれない。

が、結局それも難しい。そりゃそうだ。

ピンが出ている距離を短くするため、今度はハンダごてで温めながら力を入れてピンを引き抜こうとした。
もちろん無理。
TXB0104の基板とユニバーサル基板の2箇所がハンダ付けされているのだ。そう簡単にはいかない。

 

で、最終的にはニッパでピンを折った。
折った後でハンダ吸い取りしながらピンを抜く。
その結果が写真だ。

いやあ、ボロボロですな。
温めすぎたせいか、TXB104の基板も多少溶けてしまっている。
ICとスルーホールとの接触が切れているところもあるので、そこは直接ピンとハンダ付けし直すしかないか。。。

 

争いは何も生まない、みたいな言葉があるが、基板からの部品引き剥がしも何も生まないと思った。

2019年10月21日

[arduino]I2Cがうまく動かん

FeliCa LinkをArduinoから動かそうとした。
ブレッドボードで適当につないだときは動いたのだが、シールドとして同じように配線してみると、なぜか動かない。。。

 

FeliCa LinkとArduinoは電圧が違うので、レベルコンバータを間に入れている。

TXB0104
https://www.switch-science.com/catalog/1466/

これが、GPIOでHI/LOしているときは動いているのだが、I2C masterとして動かすと反応してくれないのだ。


まず、SDA, SCLのpinModeを見てみたい。

main.cppはここのようだ。
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.21.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\cores\arduino\main.cpp

たぶん、同じディレクトリないのwiring.cにあるinit()でピンの初期化をしている。
が、アセンブラだか組み込み命令だか知らんが、Arduinoの関数じゃないので放置だ。
たぶん、なんかうまいことやってるのだろう。

 

あきらめてWire::begin()を見てみる。
C:\Program Files\WindowsApps\ArduinoLLC.ArduinoIDE_1.8.21.0_x86__mdqgnx93n4wtt\hardware\arduino\avr\libraries\Wire\src\Wire.cpp

twi_init()を呼んでいるが、これは同じディレクトリにあるutility/twi.cだろう。
ここで、こうやっている。

  // activate internal pullups for twi.
  digitalWrite(SDA, 1);
  digitalWrite(SCL, 1);

pinMode()など出てこなかったので、main.cppから呼んでるinit()でうまいことやってるか、内部のプルアップ抵抗を変更するだけならこれでよいようになってるとか、そんなところなのか。

 

なので、変なことをしなければ、ArduinoのI2Cは内部でプルアップしてくれるのだと思う。
この状態でSDA-GND間をテスターで測ってみると、2Vくらいあった。1.8Vくらいかな。
微妙な電圧値だ。。。
だが、Wire.begin()の後でdigitalWrite(SDA, 0)とすると0Vになるので、これがプルアップ効果なのだろう。

 

レベルコンバータを使った例のサイトを見ると、ここはプルアップ抵抗をつないでいない。

https://learn.sparkfun.com/tutorials/txb0104-level-shifter-hookup-guide

ADXL345のページまで飛んだが、そっちはプルアップ抵抗を付けるような説明になっていたので、Arduinoの内蔵プルアップを使っているのだろう。
しかし、1.8V程度でやっていけるのだろうか。。。

 

あ、計測するのをテスターからオシロに変更したのだが、オシロだと5Vになってた。
もしかして私のテスター・・・値が不正確すぎ??
もう何十年も使ってるアナログテスターで、しかもそのときですら千円ちょっとで購入した気がするので、そろそろ引退してもよいのかもしれない。


5Vちゃんとあるなら、いいだろう。

しかし、だ。
これをTXB0104につなぐと、どっちも0Vになってしまうのだ。
SDA, SCLをpinMode()でOUTPUTにしてdigitalWrite()すると、ちゃんと制御できている。

image

 

というのが、今の悩みなのだ。
レベルコンバータを挟んでいるから、3.3V側でもプルアップしないとダメというだけなのだろうか。

いや、さっきまではプルアップ抵抗を付けていたのだけど、うまくいかないので全部外したのだ。
ただ、外してあれこれ試している途中で、変なところがショートしているのに気付いて、元に戻すかどうか考えているところなのだ。

そもそも、まだ3.3V側は何も取り付けていないのだ。オープンなのだ。
だからArduino側がそのまま突き抜けてくれてもいいと思うのだよ。
でもなぁ、私の今までの経験上、そういう適当な判断は間違っていることが多いのだった。。。

 

試しに、3.3V側のピンに適当な抵抗をつけてプルアップしてみた。
そうすると、ちゃんとHIになった。そして、プルアップを外してもHIが維持されている。
うーん、つまり、3.3Vにもプルアップがいるということか。

 

プルアップ抵抗として4.7kΩのをつないでみたのだが・・・スタートコンディションっぽい動作はするものの、一度立ち下がってから立ち上がる様子がない。

以前動いたときは1kΩだったので変更したが、これはこれで動きが変だ。
4.7kΩのときはLOに張り付いていたが、1kΩだとときどきHIになったりして、多少は動こうとしているように見える、というところだ。

 

うーん、なんかもう、ハンダ付けがうまくいってないとか、変なところがショートしてるとか、そういうのを心配するべきなんだろうか。。。。
実績が無ければ最初からやり直そうとするのだが、ブレッドボードの時に動いていたというのが気になってしまい、どうしても見直しをしてしまうのだよなぁ。。。