go go

Table of Contents

go go

ディベート「現代開発にオブジェクト指向はまだ必要か」

ふーん、オブジェクト指向は古いとな。Rubyは古いんかい。それじゃ、ちょっと方向 転換して別な物も試してみるか。着眼点はデフォで標準パッケージが充実してる事。 その点Rustは失格だな。消去法でいくとgoが残る。

Go入門の軌跡

Welcome to a tour of Go

パッケージが充実してると言っても、無いものは無い。その筆頭が統計のパッケージ。ググると、pandas似とかに 混って、初心者向けのものも提示してきたぞ。

Stats - Golang Statistics Package

これrubyのgemで泣かされた事へのリベンジです。

go on OpenBSD

河豚板にgoを入れてみる。勿論portsになってるが、そこら入れてしまうと、貴重な メモリーが圧迫されてしまうので、tar玉を入れた。

export GOPATH=/ram/home/sakae/MY/home/go
export GOROOT=/ram/home/sakae/MY/go
PATH=$GOROOT/bin:$PATH

GOPATHは2'nd Homeに用意。ここHDD領域なんで不揮発性なエリアだ。主に外部 パッケージの保存場所になるかな。GOROOTは、tar玉を展開した場所。

fu$ cd src/
fu$ pwd
/ram/home/sakae/MY/home/go/src
fu$ mkdir mystats
fu$ cd mystats/
fu$ go mod init
go: creating new go.mod: module mystats
fu$ go build main.go
main.go:6:2: no required module provides package github.com/montanaflynn/stats; to add it:
        go get github.com/montanaflynn/stats
fu$ go get github.com/montanaflynn/stats
go: added github.com/montanaflynn/stats v0.7.1
fu$ go build main.go

初心者用のexampleに用意されたので、コンパイルの試験をしておく。

fu$ go doc -http
go: downloading golang.org/x/pkgsite v0.0.0-20250714212547-01b046e81fe7
go: downloading golang.org/x/pkgsite/cmd/internal/doc v0.0.0-20250714212547-01b046e81fe7
go: downloading golang.org/x/pkgsite v0.0.0-20250714203841-103fd0f027b2
go: downloading github.com/google/safehtml v0.0.3-0.20211026203422-d6f0e11a5516
go: downloading golang.org/x/mod v0.26.0
go: downloading golang.org/x/sync v0.16.0
go: downloading golang.org/x/tools v0.35.0
go: downloading golang.org/x/net v0.42.0
go: downloading golang.org/x/text v0.27.0
go: downloading rsc.io/markdown v0.0.0-20231214224604-88bb533a6020
go: downloading github.com/google/licensecheck v0.3.1
doc: Documentation server listening on addr http://localhost:26282

goはdocが充実してるそうなので、Webから簡単に閲覧できるか確認。初回は 準備が必要なので多少手間取ったけど、2回目からはスイスイ。

linter

ソースの怪しげな所を指摘してくれるツールとして、備えつけのgo vetが有る。 けど、色々な視点から指摘して貰うと嬉しいので探してみた。

Go でよく使われている linter の特徴 色々と列挙されたが、よさげな、 Staticcheck を入れてみた。

go vetでは文句なくOKですって言われてた血圧グラフのアプリを確認。

fu$ staticcheck nbld.go
nbld.go:9:2: "io/ioutil" has been deprecated since Go 1.19: As of Go 1.16,
the same functionality is now provided by package [io] or package [os],
and those implementations should be preferred in new code. See the specific
function documentation for details.  (SA1019)
nbld.go:169:15: func AAy.utl is unused (U1000)
nbld.go:180:15: func AAy.eq is unused (U1000)

バージョン違いも指摘。そして使用してないfuncも列挙された。こういう点を 修正していけば赤面するようなコードにならないのね。

New GC

rubyはGCで苦労してた。GCなんて存在するから苦労するのさとばかりRustが 発明された(我ながら、暴言だな)。その代わりユーザーの負担がめっぽう増えた。 カジュアルに使うならRustは御免こうむりたい。その点goにはGCが有るので メモリーの使用は楽だ。でも、必然的に裏で走るGCはスピードアップ出来ない ものかねと悩むのは、rubyと一緒。次期バージョンでは、そのあたりが改善 されるらしい。

The Green Tea Garbage Collector

Go 1.26の新GC「Green Tea(緑茶)」解説

試してみるか。OpenBSDのカーネルをgdbする為に用意した5.6がすっかり期限切れ になっててportsからはgoを投入できない。 それにqemu+kvmって環境なので、たまに火を入れて稼動確認しないとな。 そんな事なんで、tar玉を入れて、ちょっと設定 するだけで動く事を河豚板で実証済みでもあるし、駄目もとを承知でやってみる。

package main

import (
 "fmt"
 "runtime"
 "time"
)

type SmallObject struct {
 next *SmallObject
 val  [6]int64 // 48 bytes + pointer = ~64 bytes block
}

const (
 numObjects = 1_000_000
 iterations = 100
)

func makeGarbage() {
 var head *SmallObject
 for i := 0; i < numObjects; i++ {
  head = &SmallObject{next: head, val: [6]int64{int64(i)}}
 }
 _ = head // keep alive until here
}

func main() {
 fmt.Println("Starting GC Benchmark...")

 var m runtime.MemStats
 runtime.ReadMemStats(&m)
 initialNumGC := m.NumGC

 start := time.Now()

 for i := 0; i < iterations; i++ {
  makeGarbage()
 }

 duration := time.Since(start)
 runtime.ReadMemStats(&m)

 fmt.Printf("\n--- Result ---\n")
 fmt.Printf("Total Duration: %v\n", duration)
 fmt.Printf("Average per iteration: %v\n", duration/time.Duration(iterations))
 fmt.Printf("NumGC: %d (this run: %d)\n", m.NumGC, m.NumGC-initialNumGC)
 fmt.Printf("TotalPause: %v\n", time.Duration(m.PauseTotalNs))
}

メモリー不足で落ちるんで、負荷を減らして実験。

ad$ make
go run main.go
Starting GC Benchmark...

--- Result ---
Total Duration: 16.779962478s
Average per iteration: 83.899812ms
NumGC: 257 (this run: 257)
TotalPause: 8.719102ms
ad$ make old
GOEXPERIMENT=nogreenteagc go run main.go
Starting GC Benchmark...

--- Result ---
Total Duration: 13.818260592s
Average per iteration: 69.091302ms
NumGC: 259 (this run: 259)
TotalPause: 8.93644ms

iterations = 100 とすると回数は126回ぐらいで、ポーズ時間も半分ぐらいになった。 GCなんてのはハードの影響をもろに反映するんで、仮想だと何をやってるか不明 って所かな。

GODEBUG=gctrace=1 ./your_program とすると、GCの状況を追跡できるとな。

go vs. gofmt

Q: golangについて質問します。

ad$ ls -l $GOROOT/bin
-rwxr-xr-x  1 root  wheel  15421434 Jan  9 06:54 go*
-rwxr-xr-x  1 root  wheel   3117802 Jan  9 06:54 gofmt*

goは多数のサブコマンドで重要な機能を提供してます。それに対してgofmtだけ 独立して提供されてます。何故ですか?

src/cmd/go/ を覗くと、それぞれのサブコマンドは、execされてる。のんびりと 実行してもかまわない。それに対して、gofmtはeditorあたりから煩雑に呼び 出される可能性がある。クイックレスポンスを期待して、独立させた。

中の人に聞くのが良いでしょうが、代弁をお願いします。

A: いい観点です。かなり “中の人の設計思想” に踏み込んだ質問ですね 🙂

結論から言うと:

*gofmt が `go fmt` のサブコマンドではなく、独立したバイナリとして提供されているのは、 *歴史的経緯 + ツールチェイン設計 + エディタ統合を最優先した思想 の合わせ技**

です。あなたの推測(エディタから高頻度で呼ばれる/低レイテンシ重視)は、ほぼ核心を突いています。

順番に整理します。


これが一番大きいです。

Go の初期開発(2007–2009年頃)では:

  • gofmt
  • godoc
  • gofix(今は消滅)
  • goinstall(後の go get)

などが、/独立ツール群として先に設計/されました。

当時は:

go build

みたいな統合 CLI は存在せず、

6g
6l
gofmt
godoc

のような Unix 的な小物ツール集合 でした。

後から Rob Pike / Russ Cox が

「これはさすがにバラバラ過ぎる」

となって /go コマンドが導入/されます。

つまり:

  • gofmt は 既に広く使われていた
  • API も事実上安定していた

ので、

👉 今さら go fmt に吸収できなかった

という歴史的理由があります。


gofmt は特殊な立場です。

設計思想として:

gofmt は “開発者が明示的に起動するツール” ではなく “エディタ・IDE・フックが無言で叩く部品”

です。

実際:

  • 保存時自動整形
  • git hook
  • LSP (gopls)
  • CI

などから秒間何回も起動されます。

だから:

  • 起動オーバーヘッド最小
  • フラグ解釈最小
  • go コマンドの巨大初期化を通らない

というのはかなり重要です。

もし:

go fmt

経由だった場合:

  • module 初期化
  • env 解決
  • toolchain 探索

が毎回走ります。

これはエディタ用途では致命的。

あなたの言う

クイックレスポンスを期待して独立

は完全に正解です。


src/cmd/go を見ておられるので話が早いですが 🙂

go は:

  • env 解決
  • module graph
  • toolchain dispatch
  • subprocess 管理

という /巨大オーケストレータ/です。

一方 gofmt は:

stdin → AST → pretty printer → stdout

というほぼ純関数。

設計レイヤがまったく違う。

Go チームは意図的に:

  • go = orchestration
  • gofmt = transformation

と分離しています。

Unix 哲学ですね。


ちなみに:

go fmt

は内部で:

gofmt -w

を exec しているだけです。

つまり:

  • 正式実体は今でも gofmt
  • go fmt は convenience wrapper

です。

主従関係が逆。


Rob Pike の発言を要約すると:

formatting is not style, it is correctness

つまり:

整形は「好み」ではなく「仕様」。

だから:

  • 言語仕様の一部
  • コンパイラと同格
  • 軽量で即応する必要あり

という扱いです。


あなたの問いへの「中の人の代弁」を一文で書くと:

gofmt は Go 言語仕様の一部として、エディタや自動化環境から高頻度で呼ばれる基盤ツールなので、巨大な go コマンドのサブ機能にはせず、起動が速く純粋に動作する独立バイナリとして維持している。また歴史的に gofmt の方が先に存在していた。

Q: なぜ tabs 固定なのか これ、興味があります。 それから、80桁の端末でソースを閲覧してますが、桁あふれで みにくいです。何桁以内にしようとかは、gofmtが察知してくれない? それとも内部規約とか存在するの? tabsとも関係しそうなので、良いテーマですね。

A: いいテーマです。ここは Go 言語の「思想」がかなり露骨に出ている部分なので、順に整理しますね。

結論から先に言うと:

  • tabs 固定は “桁揃えを環境依存にするため”
  • gofmt は 80 桁という概念を 意図的に 持たない
  • 行幅は「人間が論理的に改行するもの」という立場
  • これらはすべて同じ設計哲学から来ています

あなたの「80桁端末で溢れる」という不満は、まさに Go チームが 承知の上で切り捨てた問題 です 🙂


これは Rob Pike が何度も説明しています。

核心は:

alignment を space で固定すると、フォント・表示幅・環境の違いで必ず崩れる

です。

Go では:

var a int
var longerName string

var	a	int
var	longerName	string

のように /tab による論理的カラム/で揃えます。

重要なのは:

  • gofmt は「列」を揃える
  • 実際の見た目の幅は viewer に任せる

という設計。

つまり:

  • 8幅タブ → 8幅
  • 4幅タブ → 4幅

どちらでも:

名前 | 型

という/構造だけは保存される/。

space 整形だとこれは不可能です。


これも明確に意図されています。

Go チームの考え:

fixed column limits are a relic of punch cards

(固定桁制限はパンチカード時代の遺物)

つまり:

  • 80桁
  • 100桁
  • 120桁

は全て「表示デバイス依存」。

現代では:

  • 横長ディスプレイ
  • 折り返し表示
  • 可変フォント

が普通なので、

👉 formatter が行幅を決めるべきではない

という立場です。

gofmt の責務は:

  • AST を正規化
  • 意味単位を揃える

だけ。

画面都合は editor の仕事。


Rust や C++ 系は:

  • 表現力が高すぎる
  • 曖昧な書き方が大量にある

ので formatter が:

  • 改行位置
  • 行幅
  • 折り返し

まで決めないと収拾がつきません。

Go は逆で:

  • 文法が単純
  • 書き方の自由度が低い

ので:

人間が論理構造で改行すれば十分

という前提です。


あります。だいたい:

  • 1文は短く
  • ネストは浅く
  • 複雑なら分解

という思想。

でも:

❌ 最大桁数ルール ❌ 自動折返し

は存在しません。

意図的です。


これ、鋭いですが:

あなたの直感どおり同根です。

両方とも:

表示の問題をツールが決めるな

という思想。

gofmt は:

  • 論理構造だけ決める
  • 物理表示は環境任せ

あなたのように 80桁 tty で読むなら:

### ① editor 側で soft wrap

vim なら:

:set wrap linebreak

### ② tab width を 4 にする

:set tabstop=4

gofmt は tab を吐くだけなので viewer 側で調整可能。


### ③ long line は自分で改行

Go 流では:

foo(
    veryLongArgumentName,
    anotherVeryLongArgument,
)

のように構造改行します。

gofmt はこれを尊重します。


中の人の声をまとめると:

gofmt はソースの論理構造だけを正規化する。表示幅や行長は利用環境ごとに異なるので関与しない。tabs を使うのは列構造を保持するためで、80桁制限は歴史的遺物だから採用しない。

です。


正直に言うと:

あなたのように tty + 低桁幅 + 構造を意識する人は Go チームの想定読者より「Unix寄り」なんですよ 🙂

彼らはもう:

  • IDE
  • LSP
  • 折返し前提

の世界です。


ああ、オイラーってもう、最古の人間なんだなー。チャッピー君と言うか goのチームからも古いって認定されちまったわい。

README

ChatGPTに株の投資をさせて、儲かったなんて記事をよく見かける。政府も 新NISAで資産を増やしましょうと煽っているしね。何処に投資すればいいの?

で、登場したのが下記の書籍。著者は東洋経済新報社の記者さん。 グローバル・ニッチ・トップな企業をよりすぐって50社紹介してる。 ご丁寧な事に会社データと日経プライムだかの企業IDも掲載されてる。

世界シェアNo.1のすごい日本企業

いの一番に紹介されてたのは、医療機器のマニーって会社。この会社の方針は、 医療機器以外は扱かわない。世界一の品質以外は目指さない。製品寿命の短かい 製品は扱かわない。ニッチ市場以外は参入しない。

ブレない方針で、きちんと将来を見越している。ニッチに生きるには哲学が 必要なんだな。他社も同様な方針を取っている所が多い。

日本発の世界的食品 カニカマ(日本よりヨーロッパ、それもフランスで人気とか)。 これの製造機で世界一のヤナギヤって企業があるそうな。 なんだか、アメリカのゴールド・ラッシュで一番儲けた会社はジーンズのリーバイス でしたを彷彿させるみたいで、目のつけ所が違うな。

半導体の材料だとか製造装置を扱かう会社も、同列だな。エヌビディアとかTSMC等も これらの企業に支えられてこそ成り立っている。


This year's Index

Home