package main
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"time"
"github.com/mattn/go-shellwords"
"github.com/mattn/go-zglob"
)
func html_minifier(from string, to string) {
cmd := fmt.Sprintf(`
sh -c 'html-minifier %v \
--collapse-boolean-attributes \
--collapse-whitespace \
--remove-attribute-quotes \
--remove-comments \
--remove-empty-attributes \
--remove-redundant-attributes \
--remove-script-type-attributes \
--remove-style-link-type-attributes \
--html5 \
--use-short-doctype \
--minify-js \
--minify-css > %v'
`, from, to)
args, _ := shellwords.Parse(cmd)
exec.Command(args[0], args[1:]...).Run()
}
func main() {
dir := os.Args[1]
var minifySize, html_minifierSize, originalSize int64
var minifyTime, html_minifierTime int64
paths := getPaths(dir, "*.html")
for _, path := range paths {
fileinfo, _ := os.Stat(path)
originalSize += fileinfo.Size()
}
for _, path := range paths {
cmd := fmt.Sprintf("sh -c 'minify %s > %s'", path, path+".min")
args, _ := shellwords.Parse(cmd)
t := time.Now().UnixNano()
exec.Command(args[0], args[1:]...).Run()
minifyTime += time.Now().UnixNano() - t
fileinfo, _ := os.Stat(path+".min")
minifySize += fileinfo.Size()
}
for _, path := range paths {
t := time.Now().UnixNano()
html_minifier(path, path+".min")
html_minifierTime += time.Now().UnixNano() - t
fileinfo, _ := os.Stat(path+".min")
html_minifierSize += fileinfo.Size()
}
fmt.Printf("file num: %v\n", len(paths))
fmt.Printf("original: %v\n", originalSize)
fmt.Printf("Minify: %v, %v\n", minifySize, time.Duration(minifyTime))
fmt.Printf("html_minifier: %v, %v\n", html_minifierSize, time.Duration(html_minifierTime))
}
Goで即興スクリプトを書いてみて気になった点は3つほど。(1)RubyのDir.globみたいな再帰検索はこれまで自作していましたが、最近はgithub.com/mattn/go-zglobを利用すると簡単に書けるようになりました。どんどんmattnさんのライブラリで埋まっていく…。
(2)ベンチマークにはtestingという標準ライブラリがあります。時間やメモリを計測するには非常に便利ですが、計測精度を高めるために勝手に連続実行する仕組みになっています。同時に色々な情報を処理しながら計測しようとすると少し困ります。手軽な計測であればtime.Now()で地道に計算するのが楽かなあ。
(3)外部コマンドを実行するにはexec.Command(args)を使いますが、argsには文字列の配列を渡す必要があり面倒です。github.com/mattn/go-shellwordsを利用するとシェル上での実行文字列を配列に変換してくれるのでかなり楽になります。ただしcommand > outのようなコマンド内での出力には対応していないので、sh -c 'command > out'のような形式に変更して実行する必要がありました。
Go言語はスクリプトごとにbuildしていると容量がかなり無駄になりますが、以下の方法でバイナリサイズを小さくすれば気にならない程度には小さくなります。
$ sudo apt-get install upx-ucl
$ go get github.com/pwaller/goupx
$ go build -ldflags '-s' test.go
$ goupx -9 test # or goupx test
もう少し色々なパターンで記述の容易さを確認してみたいです。
0 件のコメント:
コメントを投稿