
こんにちは。よっしーです(^^)
本日は、Go言語のよくある質問 について解説しています。
背景
Go言語を学んでいると「なんでこんな仕様になっているんだろう?」「他の言語と違うのはなぜ?」といった疑問が湧いてきませんか。Go言語の公式サイトにあるFAQページには、そんな疑問に対する開発チームからの丁寧な回答がたくさん載っているんです。ただ、英語で書かれているため読むのに少しハードルがあるのも事実で、今回はこのFAQを日本語に翻訳して、Go言語への理解を深めていけたらと思い、これを読んだ時の内容を備忘として残しました。
Implementation
なぜウイルススキャンソフトウェアが、Goディストリビューションやコンパイル済みバイナリが感染していると判断するのか?
これは、特にWindowsマシンでよく発生する現象で、ほぼ常に誤検知です。商用ウイルススキャンプログラムは、他の言語からコンパイルされたものほど頻繁に見かけないGoバイナリの構造に混乱することがよくあります。
Goディストリビューションをインストールしたばかりで、システムが感染していると報告する場合、それは確実に間違いです。本当に徹底的に確認するには、ダウンロードページのチェックサムとダウンロードしたものを比較することでダウンロードを検証できます。
いずれにせよ、報告が誤りだと思われる場合は、ウイルススキャナーの提供元にバグを報告してください。時間が経てば、ウイルススキャナーもGoプログラムを理解できるようになるかもしれません。
解説
この問題は何について説明しているの?
Goでプログラムを作ってコンパイルすると、こんな警告が出ることがあります:
⚠️ Windows Defender
脅威が検出されました: Trojan:Win32/Wacatac.B!ml
ファイル: hello.exe
「え!? ウイルス!? 自分で作ったプログラムなのに!?」
安心してください。これはほぼ100%誤検知(false positive)です。
基本的な用語
- 誤検知 (false positive): 実際には問題ないのに、問題があると誤って検出すること
- ウイルススキャナー: ウイルスやマルウェアを検出するソフト
- バイナリ: コンパイル後の実行ファイル
- チェックサム: ファイルの「指紋」のようなもの、改ざん検出に使う
- ヒューリスティック検査: 既知のウイルスパターンではなく、「怪しい動作」を検出する方法
なぜGoのバイナリが誤検知されるのか?
理由1: 見慣れない構造
ウイルススキャナーの学習:
たくさん見たもの:
C/C++でコンパイルされたプログラム
.NET Framework プログラム
Visual Studioで作られたプログラム
↓
これらは「正常」と学習
あまり見ないもの:
Goでコンパイルされたプログラム
↓
「怪しい!?」と判断
例え:
警察犬が学習しているもの:
犬、猫、人間 → 安全
初めて見るもの:
カピバラ → 「何これ!? 危険かも!」
実際には無害なのに、見慣れないから警戒してしまう。
理由2: 静的リンク
前の質問で学んだように、Goは静的リンク:
Goのバイナリ:
┌────────────────────┐
│ あなたのコード │
│ + ランタイム │
│ + 全ての依存 │ ← 大きい、自己完結
└────────────────────┘
一般的なプログラム:
┌──────────┐
│ コード │ ← 小さい、外部依存
└──────────┘
↓
システムDLL
ウイルススキャナーの判断:
「このプログラム、システムDLLを使わない...」
「全部自分で持ってる...」
「マルウェアがよくやる手口だ!」
→ 誤検知!
理由3: 実行時の特殊な動作
Goのランタイムは独特:
- 独自のスケジューラ
- 独自のメモリ管理
- 独自のスタック管理
ウイルススキャナー:
「通常のプログラムと動きが違う...」
「怪しい...」
→ 誤検知!
理由4: UPX圧縮
バイナリサイズを小さくするためにUPXで圧縮すると:
upx --best hello.exe
ウイルススキャナー:
「実行ファイルが圧縮されている!」
「マルウェアがよく使う手法!」
→ 誤検知率UP!
実際、マルウェアは検出を逃れるために圧縮を使うことがあります。
よくある誤検知のパターン
パターン1: Go本体のインストール時
シナリオ:
1. go1.21.windows-amd64.msi をダウンロード
2. インストール実行
3. Windows Defenderが警告:
「Trojan:Win32/Wacatac が検出されました」
これは間違いです! 公式サイトからダウンロードしたGoは安全です。
パターン2: 自作プログラムのコンパイル直後
シナリオ:
1. hello.go を作成
2. go build hello.go
3. hello.exe が生成される
4. すぐに削除される!
5. 「脅威を削除しました」と通知
あなたのプログラムが削除された! でも、ウイルスではありません。
パターン3: ネットワーク機能を使うプログラム
package main
import (
"net/http"
"fmt"
)
func main() {
resp, _ := http.Get("https://example.com")
fmt.Println(resp.Status)
}
ウイルススキャナー:
「ネットワーク通信している!」
「外部と通信するプログラム!」
「怪しい!」
→ 誤検知!
対処方法
方法1: ウイルススキャナーの例外設定
Windows Defender の場合:
- Windows セキュリティを開く
- ウイルスと脅威の防止
- 設定の管理
- 除外セクション
- 除外の追加または削除
追加する除外:
フォルダ: C:\Program Files\Go
フォルダ: C:\Users\YourName\go
フォルダ: C:\Users\YourName\Projects
注意: 本当に安全なフォルダだけを除外してください!
方法2: チェックサムで検証
公式ダウンロードの確認:
# ダウンロードしたファイルのチェックサム
certutil -hashfile go1.21.windows-amd64.msi SHA256
出力例:
SHA256 hash of go1.21.windows-amd64.msi:
a1b2c3d4e5f6...
公式サイトと比較:
https://go.dev/dl/
→ Checksums を確認
→ 一致すれば安全!
方法3: 段階的な対応
ステップ1: 冷静に判断
質問1: 公式サイトからダウンロードした?
→ YES: ほぼ確実に誤検知
質問2: 自分で書いたコード?
→ YES: ほぼ確実に誤検知
質問3: 怪しいサイトからダウンロード?
→ YES: 本当に危険かも!
ステップ2: 検証
1. チェックサムを確認
2. VirusTotalでスキャン(オンラインサービス)
3. 複数のスキャナーで確認
ステップ3: 報告
1. ウイルススキャナー提供元に誤検知を報告
2. Goコミュニティにも報告(GitHub Issue)
VirusTotal での確認方法
VirusTotal: 複数のウイルススキャナーで一度にチェックできるサービス
1. https://www.virustotal.com にアクセス
2. ファイルをアップロード
3. 結果を確認:
例:
60個のスキャナー中:
- 58個: 問題なし
- 2個: 検出
→ 誤検知の可能性が高い
注意:
- 機密情報を含むプログラムはアップロードしない
- アップロードしたファイルは公開される
各ウイルススキャナーでの報告方法
Windows Defender (Microsoft)
1. Windows セキュリティを開く
2. 保護の履歴
3. 該当する検出を見つける
4. 「誤検知として報告」をクリック
または:
https://www.microsoft.com/en-us/wdsi/filesubmission
Avast
https://www.avast.com/false-positive-file-form.php
AVG
https://www.avg.com/en-us/false-positive-file-form
Kaspersky
https://opentip.kaspersky.com/
なぜこの問題が起きるのか(技術的詳細)
Goバイナリの特徴
1. 大きなバイナリサイズ
通常のC/C++プログラム: 数十KB
Goプログラム: 数MB
ウイルススキャナー:
「大きい = たくさんコードが詰まっている」
「マルウェアかも?」
2. 独特なバイナリ構造
PE (Portable Executable) ヘッダー:
- Goは独自のセクション配置
- 通常と異なるエントリーポイント
- カスタムローダー
ウイルススキャナー:
「見慣れない構造...」
3. ランタイムの動的動作
実行時:
- メモリを動的に確保
- スタックを動的に拡張
- ゴルーチンを作成・破棄
ウイルススキャナー:
「動的な動作が多い...」
「マルウェアっぽい?」
実際の対処例
例1: 簡単なHTTPサーバー
コード:
package main
import (
"fmt"
"net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}
func main() {
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
コンパイル:
go build -o server.exe server.go
Windows Defender の反応:
脅威: Trojan:Win32/Casdet!rfn
状態: 削除されました
対処:
# 1. 除外フォルダに追加
# 2. 再ビルド
go build -o server.exe server.go
# 3. 実行
./server.exe
# → 問題なく動作!
例2: コマンドラインツール
コード:
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage: tool <filename>")
return
}
data, _ := os.ReadFile(os.Args[1])
fmt.Println(string(data))
}
誤検知の理由:
- ファイルシステムアクセス
- コマンドライン引数の処理
対処:
- プロジェクトフォルダを除外設定
- ウイルススキャナーに報告
予防策
1. 開発フォルダを除外設定
推奨構成:
C:\Users\YourName\
├── go\ ← Go modules キャッシュ
└── Projects\ ← 開発フォルダ
├── project1\
├── project2\
└── ...
除外設定:
C:\Users\YourName\go
C:\Users\YourName\Projects
2. リアルタイムスキャンの調整
Windows Defender:
設定 → ウイルスと脅威の防止
→ リアルタイム保護
→ (必要に応じて)一時的に無効化
注意: 開発中のみ、安全な環境で!
3. ビルドフラグの調整
# デバッグ情報を含める(誤検知率が下がることも)
go build -ldflags="-s -w" main.go
# または、通常ビルド
go build main.go
実は、デバッグ情報を削除すると誤検知が増えることも…
コミュニティの取り組み
Go チームの対応
1. ウイルススキャナー企業に連絡
2. Goバイナリの特徴を説明
3. 誤検知データベースに追加してもらう
進行中ですが、完全解決には時間がかかります。
ユーザーができること
1. 誤検知を報告
→ ウイルススキャナー企業
→ Goのissue tracker
2. データを共有
→ どのスキャナーで検出されたか
→ どんなプログラムか
3. 忍耐強く待つ
→ 時間とともに改善される
まとめ
Goバイナリの誤検知について
- ほぼ確実に誤検知
- 公式からのダウンロード
- 自作プログラム
- 特にWindows環境
- 原因:
- 見慣れない構造
- 静的リンク
- 独特なランタイム動作
- 対処法:
- 除外設定
- チェックサム確認
- 報告
実用的なアドバイス
| 状況 | 対応 | 優先度 |
|---|---|---|
| Go本体のインストール | 除外設定 + チェックサム確認 | 🔴 高 |
| 開発中のプログラム | プロジェクトフォルダを除外 | 🔴 高 |
| 配布用プログラム | デジタル署名 | 🟡 中 |
| 誤検知の報告 | スキャナー企業に連絡 | 🟢 低 |
やるべきこと
すぐに:
- ✅ 開発フォルダを除外設定
- ✅ Go インストールフォルダを除外設定
- ✅ チェックサムで公式ダウンロードを確認
余裕があれば:
- ⭐ VirusTotalで確認
- ⭐ ウイルススキャナーに誤検知を報告
- ⭐ Goコミュニティに情報共有
やってはいけないこと
❌ ウイルススキャナーを完全に無効化 → 本当の脅威から無防備に
❌ 怪しいサイトからGoをダウンロード → 本当にウイルスの可能性
❌ すべてのプログラムを信用 → 自分で書いたコードのみ信用
長期的な展望
現在:
Goは比較的新しい
ウイルススキャナーが学習中
数年後:
Goがより普及
誤検知が減少
将来:
ほとんど問題なし?
時間とともに、ウイルススキャナーも進化し、Goバイナリを正しく認識できるようになるはずです。
重要な心構え:
- 😱 パニックにならない
- 🔍 冷静に確認する
- 📝 必要なら報告する
- 💪 開発を続ける!
この問題は、Goが「新しくて優れている」ことの副作用とも言えます。ウイルススキャナーが追いついていないだけで、あなたのプログラムは安全です。適切な対処をすれば、開発には全く支障ありません!
おわりに
本日は、Go言語のよくある質問について解説しました。

何か質問や相談があれば、コメントをお願いします。また、エンジニア案件の相談にも随時対応していますので、お気軽にお問い合わせください。
それでは、また明日お会いしましょう(^^)

コメント