cosplayコマンドをGo言語で書き直した話
以前 カジュアルに環境変数を変えたcmdを動かすためにcosplayコマンド作った - chikuchikugonzalezの雑記帳 という記事で cosplay とかいうコマンド作ったんですが、このたびGo言語をやることになったのでキャッチアップも兼ねて移植してみてた。
↓違い
cosplay | cosplay2 | |
---|---|---|
言語 | C# | Go言語 |
環境 | コマンドプロンプト | コマンドプロンプト, PowerShell (仮) |
で、ちょろちょろハマったのでそのメモを残しておこうかと
interfaceとstructのあれ?ってなったとこ
Go言語の構造体にメソッドを追加するときってだいたい以下のように書くらしいので、それに従ってました。
type Hoge struct {} func (self *Hoge) Fuga() { /* なんかする */ }
で、インターフェイス使うとあたかも同じ型のように使える、ってことでサブコマンドの実装に使ったり。
そしたらなんか作法が違いましてね
package main type Hoge interface { Hoge() } type HogeHoge struct {} // ポインタダメだって //func (self *HogeHoge) Hoge() { } // こっち func (self HogeHoge) Hoge() { } func hoge(hoge Hoge) {} func main() { var h = HogeHoge{} hoge(h) }
違いがわからん(´・ω・`)
os.Getenv/os.Setenv/os.Environ
こっちがエッ(゚Д゚≡゚Д゚)マジ?ってなったやつ。Windowsの仕様とかも絡んでるかもしれん。
os/execパッケージ使うとプロセスを起動できるんですが、そのときに環境変数を指定しようとするとこんなことになります。
func run() { cmd = exec.Command("notepad.exe") env = []string{"hoge=fuga"} cmd.Env = env cmd.Run() }
単に'key=value'形式の文字列が必要ってことなんですが、ここでねぇ(´・ω・`)
func run() { var cmd = exec.Command("cmd.exe") var env = []string{"hoge=fuga", "HOGE=FUGA"} cmd.Env = env cmd.Stdin = os.Stdin cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr cmd.Run() }
このようにして起動したcmdでsetをたたいて環境変数を見るとこうなります
C:\>set COMSPEC=C:\WINDOWS\SysWOW64\cmd.exe hoge=fuga HOGE=FUGA PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.JS;.WS;.MSC PROMPT=$P$G C:\>
なお、os.Setenvとかのほうはこんなことにならんかった。
あと気になってcmd起動して
C:\> set Hoge=Fuga C:\> set HOGE=FUGA
したけど、その結果は「Hoge=FUGA」だった
その他
mapのコピーってどうやるのがいいのかねぇ