2017/08/17


https://play.golang.org/p/CHGYhtzRsK Go 1.8.3で『GOOS="darwin"』だと完走するけど、『GOOS=...

Go 1.8.3で『GOOS="darwin"』だと完走するけど、『GOOS="windows"』だと途中でエラーになるプログラム。


osやsyscallパッケージを使っている時、こういう事があって当然なのかパッケージの実装に問題があるのか判断する規準となりそうな記述って公式になにかありますでしょうか。

https://plus.google.com/u/0/103737163485109218200/posts/gfNS2Bz4QrH?cfem=1

UNIX だと以下のコードはパスするのに Windows だとエラーになるという話。

package main

import (
    "fmt"
    "os"
)

func chk(err error) {
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

func main() {
    f, err := os.Create("log.txt")
    chk(err)
    defer f.Close()
    err = os.Rename("log.txt""log.txt.bak")
    chk(err)

    os.Remove("log.txt")
    os.Remove("log.txt.bak")
}

UNIX の場合、ファイルを開いている最中にファイルを削除するとファイルシステム上からは unlink されるけど、実際は存在していてファイルの読み込みが出来ます。そして close(2) されたタイミングで削除されます。Windows の FILE_SHARE_DELETE は一見、UNIX のそれっぽく見えるのですが動作が異なります。

例えば test.txt というファイルを作り以下のコードを実行します。

#include <windows.h>
#include <stdio.h>

int
main(int argc, char* argv[]) {
  HANDLE h = CreateFile("test.txt",
      GENERIC_READ | GENERIC_WRITE,
      FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  getchar();
  char buf[256] = {0};
  DWORD nread;
  printf("%d\n", ReadFile(h, buf, 256, &nread, NULL));
  printf("%s,%d\n", buf, nread);
  return 0;
}

getchar() で処理が停止している間に別のコマンドプロンプトでファイルを消してみて下さい。まずは実行

delete1

そして削除。ファイルが消えると思いきや残っています。そしてアクセスするとエラーになります。

delete2

Windows の FILE_SHARE_DELETE の動作は UNIX のそれとは異なるのです。例えばファイルを消した後で、ファイルが存在しないつもりで処理を続行してしまうと別のエラーが発生する事になります。

package main

import (
    "fmt"
    "os"
)

func chk(err error) {
    if err != nil {
        fmt.Fprintln(os.Stderr, err)
        os.Exit(1)
    }
}

func main() {
    f, err := os.Create("log.txt")
    chk(err)
    defer f.Close()
    f.Close()
    err = os.Rename("log.txt""log.txt.bak")
    chk(err)

    os.Remove("log.txt")
    os.Remove("log.txt.bak")
}

この様な OS 間の動作の違いを吸収する事は言語レベルでは出来ません。マルチプラットフォームで動作するコードを書きたいと思われるのであれば、os.Rename や os.Remove の前に Close する事をおすすめします。

ちなみに「みんなのGo言語」にも解説が書いてあります。

みんなのGo言語[現場で使える実践テクニック] みんなのGo言語[現場で使える実践テクニック]
松木雅幸, mattn, 藤原俊一郎, 中島大一, 牧大輔, 鈴木健太
技術評論社 / (2016-09-09)
 
発送可能時間:


2017/07/24


ひさびさ Vim のエントリを書く気がします。

今から4年ほど前、Vim にスレッドセーフなメッセージキューが欲しいというメールが vim-dev 届きます。

[PATCH] Proof of concept: thread-safe message queue
https://groups.google.com/forum/#!searchin/vim_dev/tarruda%7Csort:relevance/vim_dev/65jjGqS1_VQ/fFiFrrIBwNAJ

その時はまだ、vim-dev の中にも「Vim はエディタだし必要ない」といった空気があったと思います。

[PATCH] Non-blocking job control for vimscript
https://groups.google.com/forum/#!searchin/vim_dev/tarruda%7Csort:relevance/vim_dev/QF7Bzh1YABU/02-YGr7_sCwJ

そしてその数か月後、もう一つのメールが届きます。ノンブロッキングでプロセスを制御する為のパッチです。

このパッチに関して vim-dev は特に反対意見を持っていませんでした。しかし Bram から反応が得られませんでした。昔から vim-dev を知っている人であれば分かると思うのですが、Bram はまずこういった機能追加の要望があった際にはまず皆の反応を確かめます。盛り上がったら取り込むし、盛り上がらなかったらボツという事です。僕も、大昔にソケット通信のパッチを送ってボツにされた事もありますし、mruby を組み込むパッチを送って誰からも相手されなかった事があります。

その反応が気に入らないという人もいました。この2つのメールを送ってきた人、その人もそうでした。そう、この2つのメールを送ってきた人こそが後に Neovim を作る事になった人です。Neovim は Vim のコードをベースに色々な機能を盛り込み、Vim と差別化する事で資金を調達しました。その中でも特徴的だったのが端末機能です。Vim のウィンドウの一つに端末を割り当てられる事で Vim の中だけで色々なシェル操作を完結できるという、とてもキャッチ―な物でした。非同期通信やタイマーといった API は現在の Vim にも備わっています。Bram は元々 fork を参考にしないという頑固な人なので、同じ様な機能を実装するのに時間は掛かってしまったかもしれませんが、channel/job に関しては Neovim 以上の物が実装されています。しかしながらこの端末機能についてはサポートされてきませんでした。ところがつい先日の 7/3 突然 Bram が口を開きました。

Adding terminal emulator support in Vim
https://groups.google.com/forum/#!topic/vim_dev/Q9gUWGCeTXM

長い間、私は Vim の中で端末エミュレータを追加する事がはたして良いアイデアであるのか疑問を持ち続けてきました。 それは危険なことですし、規模も大きくなり、そしてメンテナンスの悪夢にもなり得ます。 しかしそれと同時に、これは非常に、非常に便利になり得ます。

私が今回これを望んだ理由は、ssh 接続で Vim をデバッグする為です。 私はローカルで程よい設定をしていますが、家にいない時はいつも苦しんでいます。 これらの多くの制限は、いつも私が家に帰りデバッグする時間を延期してしまいます。 これを提供するプラグインがありますが、Vim をデバッグするには端末で実行する必要があるのです。

そういって突然 terminal への興味を示しました。僕は以前、Qiita にこんな記事を書いた事がありました。

Vim のソースのいじり方(:terminal を作るまで) - Qiita

この記事は [Vim Advent Calendar 2016](http://qiita.com/advent-calendar/2016/vim)、18日目の記事です。 # はじめに ここ数年で、...

http://qiita.com/mattn/items/ee438479b09055a2f305

そこで作った物を Bram に見せたところ、面白いと興味を持ってくれました。しばらくして Vim のマスターブランチに :terminal の実装が入り始めます。しかし標準入出力を操作する dumb 端末でしかありませんでした。

これはいっちょやってやるかと、winpty を使って Windows で terminal を動かすパッチを送りつけました。

support :terminal on Windows by mattn · Pull Request #1854 · vim/vim · GitHub

diff --git a/src/terminal.c b/src/terminal.c index df40866ba..bc632e7cb 100644 --- a/src/terminal.c ...

https://github.com/vim/vim/pull/1854

7/19 日の事ですから、わずか3日前の事です。Bram もとても興味を持ってくれた様でした。それから Bram と僕でパッチを書き続け、先ほど入ったパッチでようやく一段落した様な気がします。

terminal

まさか4年前に、Vim が数年後にこんな事が出来る様になるなんって思っていませんでした。自分でパッチを書いておきながら少し感動してしまいました。右上のウィンドウでこのブログ記事を書き、右下のウィンドウで ssh ログインして UNIX 版の動作検証、左でツイッターのストリームをダラダラと流し続けている光景です。

ちなみに Windows での terminal は Neovim も実現できていません。

元々、コマンドプロンプトで生活しており、Vim を常駐しない派でしたので今後この端末機能を使うかどうかは正直分かりませんが、何か Vim の新しい時代が来た様な気がしており、久しぶりに書いて良かったなと思えるパッチでした。

まだもう少しバグがあるかもしれませんし、安定しないかもしれませんが、引き続き精力的に開発していく予定です。もちろん「vim-jp が Vim の新しい機能を作っていくんだ」という気持ちに変わりはありません。ぜひ新しく追加された端末機能を使ってみて下さい。


2017/07/14


結構前から、そろそろ .NET Core を使ったお仕事とかやっていきたいなと思っていて、その際に Linux でちゃんと動くのかを確認しておきたかった。ただインターネットを見てもそれほど良い情報が見当たらず、これは誰も試してないのかもなと思い仕方がないので自分で作って体験してみる事にした。

GitHub - mattn/dotnet-blog

README.md dotnet-blog Markdown friendly blog engine inspired with Jekyll written in Microsoft .NET C...

https://github.com/mattn/dotnet-blog

Markdown で記事が書けて、Jekyll と同様に Liquid でテンプレート制御が行えて、さらに Git と連携するブログエンジンです。

ディレクトリ構成は Jekyll とほぼ同じで、_posts2017-07-13-タイトル.md の形式のファイルを置いたら勝手に _layouts の中のテンプレートが適用されてかっちょいいサイトで表示されるという物です。設定ファイルも _config.yml に書きます。

title: "塩梅ドットコム"
base-url: "http://mattn.apphb.com"
clone-url: https://github.com/mattn/dotnet-blog-posts.git

この clone-url に書かれたリポジトリから、_posts_layouts および _site といったファイルを git pull してローカルに展開します。サンプルのリポジトリも置いておきました。

GitHub - mattn/dotnet-blog-posts

Dismiss Join GitHub today GitHub is home to over 20 million developers working together to host and ...

https://github.com/mattn/dotnet-blog-posts

一度デプロイ出来たら、あとはこちらのリポジトリを更新してサイトの /pull に POST を送ると更新されます。この仕組みはもしかするといずれ変更するかもしれません。

トップ画面

トップ画面や

記事の画面

記事もきちんと表示されます。

とまぁ、こんな感じのブログエンジンを書いてみた訳だけど、実は今回はあえて Vim を使わず全て Visual Studio Code だけで開発を行った。これは仕事で使っていくなら僕だけじゃなく IDE を使いたい人がどの程度苦労するかも把握しておきたかったから。Visual Studio Code の C# 開発環境は以前まではそこそこ酷くて、まともな開発なんて出来ないんじゃないのって思ってたけど今回の開発でそのイメージは一蹴された。あの小気味良い軽快な動作をするエディタの様な IDE 上で、dotnet の restore やブレイクポイントを貼ったデバッグ、入力補完などほぼ問題なく扱えた。

また Windows で開発すると同時に Linux でも動作検証を行った。今回使った DotLiquid や CommonMark などは netcoreapp1.1 (.NET Core 1.1 ターゲット) でも問題無く使えていたし、publish して IIS 上で動作する事も確認出来た。気を付けないといけないのは、パス周りは「必ず」Path.Combine などを使うという事くらいだった。当初は 2~3 日くらいでこの検証を行う予定だったが、ちょっといろいろと忙しく1週間程度掛かってしまった。けれど開発の手順に慣れれば数日でそこそこ品質の良いマルチプラットフォーム向けのウェブアプリケーションを開発する事も出来るという結論に至った。まだテストスイートやインフラ周りで問題が無いかちゃんと検証できてないのでいきなり仕事で使おうとは思ってないけど、そこそこ近い未来で使う時が来るんじゃないかと思った。

C# 7 and .NET Core 2.0 Blueprints: Build effective applications that meet modern software requirements (English Edition) C# 7 and .NET Core 2.0 Blueprints: Build effective applications that meet modern software requirements (English Edition)
Dirk Strauss, Jas Rademeyer
Packt Publishing / (2018-03-28)
 
発送可能時間: