Journal

CGOを切ると、配布の気持ちが少し軽くなる

Goで小さな道具を書くとき、私は機能より先に最後の配り方を想像します。自分のPCで動くだけなら何でもいいのですが、別のWindowsマシンへ渡す段になると、話が急に現実的になります。zipを置いて終わりにしたいですし、変な前提条件は増やしたくありません。

以前、Windows向けの小さなGo製CLIを人に渡したとき、こちらでは普通に動いたのに、相手のPCでは起動しませんでした。原因は大げさなものではなくて、CGOを有効にしたままビルドしていたことでした。あの手のつまずき方は、一度やると忘れません。それ以来、配布前にCGO_ENABLED=0をまず疑うようになりました。

軽くなるのはサイズではなく前提

CGOを切ると、毎回ファイルサイズが劇的に減るわけではありません。そこを期待すると少し肩透かしです。今回、os/user を使うだけの短いプログラムで見比べると、CGOありのバイナリは 2,330,683 バイト、CGOなしは 2,373,476 バイトでした。むしろ少しだけ大きくなっています。

それでも私がCGOを切りたくなるのは、軽くなる場所が別だからです。バイナリそのものではなく、起動に必要な前提が減ります。配布で怖いのは、数十KBの差ではありません。渡した先の環境に、こちらが勝手に期待してしまうことです。

何が変わるのか

試したコードはこれです。

package main

import (
    "fmt"
    "os/user"
)

func main() {
    u, err := user.Current()
    if err != nil {
        fmt.Println("user lookup failed:", err)
        return
    }
    fmt.Println("hello", u.Username)
}

ビルドはこうしました。

CGO_ENABLED=1 go build -o app-cgo main.go
CGO_ENABLED=0 go build -o app-nocgo main.go

Linux上で file と ldd を見ると、差はかなりはっきり出ます。

$ file app-cgo
ELF 64-bit LSB executable, x86-64, dynamically linked

$ ldd app-cgo
libc.so.6 => /lib64/libc.so.6

$ file app-nocgo
ELF 64-bit LSB executable, x86-64, statically linked

$ ldd app-nocgo
動的実行ファイルではありません

この結果を見ると、気分の問題ではなく、本当に依存の形が変わっています。CGOありのほうは libc を見に行きます。CGOなしのほうは、少なくともこの程度のコードなら単体で閉じます。私はこういう差をかなり信用します。説明のうまさより、ldd の一行のほうが話が早いです。

単体バイナリの雑な強さ

単体バイナリが好きなのは、上品だからではありません。雑に扱えるからです。フォルダへ置けますし、消せますし、別のPCへそのまま投げることもできます。そういう動きが素直にできます。インストーラーの気配を読まなくてよくなるだけで、かなり気が楽になります。

メインPCがWindowsだと、この感覚はわりと切実です。便利な道具ほど、あとで静かに常駐したり、アンインストール後に何かを残したりします。だから私は、配る側に回るときも余計なものを背負わせたくありません。Goのよさは、そういう小さな潔癖さと相性がいいところだと思います。

もちろん、何でもCGOなしで済むわけではありません。Cライブラリに触るなら必要になりますし、SQLiteまわりでも選ぶパッケージ次第では普通に入ってきます。そこは割り切るしかありません。ただ、標準ライブラリで足りる小さな道具まで重くする理由も、あまり感じません。

まず疑う場所がひとつ減る

不具合が出たとき、疑う場所は少ないほうが助かります。コードが悪いのか、入出力が悪いのか、配布物の作りが悪いのかを先に切り分けたいです。その切り分けが先にできるだけでも、頭が散りません。そこへさらに共有ライブラリの都合まで混ざると、急に面倒になります。AIにボイラープレートを書かせる時代でも、この手の面倒だけは消えません。むしろ最後に人間が引き取る種類の面倒です。

だから私は、Goで小さなCLIを書くときほどCGOを切りたくなります。最適化の話というより、態度の話です。自分のPCで確かめたものを、そのまま渡しやすい形へ寄せておきたいです。Goが現代のC言語に見える瞬間は、たぶんこういう地味なところにあります。

Previous