Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
fmt
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
ktr
January 25, 2018
Technology
0
4.3k
fmt
ktr
January 25, 2018
Tweet
Share
More Decks by ktr
See All by ktr
詳解 MCP Go SDK / MCP Go SDK
ktr_0731
3
550
あまり知られていない MCP 仕様たち / MCP specifications that aren’t widely known
ktr_0731
0
450
CLI ツールを Go ライブラリ として再実装する理由 / Why reimplement a CLI tool as a Go library
ktr_0731
3
1.4k
激動の一年を通じて見えてきた「技術でリードする」ということ
ktr_0731
8
10k
Monorepo における Go テストの差分実行 / Running Differential Go Tests in a Monorepo
ktr_0731
1
380
Designing libraries in Go way
ktr_0731
7
1.6k
Go Modules and Proxy Walkthrough
ktr_0731
8
27k
ソフトウェアの複雑さに立ち向かう技術 / Tackling software complexity
ktr_0731
0
230
Fuzzy finder as a Go library
ktr_0731
3
6.2k
Other Decks in Technology
See All in Technology
30万人の同時アクセスに耐えたい!新サービスの盤石なリリースを支える負荷試験 / SRE Kaigi 2026
genda
1
460
ファインディの横断SREがTakumi byGMOと取り組む、セキュリティと開発スピードの両立
rvirus0817
1
1.2k
Agile Leadership Summit Keynote 2026
m_seki
1
530
Azure Durable Functions で作った NL2SQL Agent の精度向上に取り組んだ話/jat08
thara0402
0
150
広告の効果検証を題材にした因果推論の精度検証について
zozotech
PRO
0
140
ZOZOにおけるAI活用の現在 ~開発組織全体での取り組みと試行錯誤~
zozotech
PRO
5
4.9k
AIと新時代を切り拓く。これからのSREとメルカリIBISの挑戦
0gm
0
810
変化するコーディングエージェントとの現実的な付き合い方 〜Cursor安定択説と、ツールに依存しない「資産」〜
empitsu
4
1.3k
~Everything as Codeを諦めない~ 後からCDK
mu7889yoon
3
290
OWASP Top 10:2025 リリースと 少しの日本語化にまつわる裏話
okdt
PRO
2
320
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.3k
Sansan Engineering Unit 紹介資料
sansan33
PRO
1
3.8k
Featured
See All Featured
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
62
49k
Designing for Performance
lara
610
70k
The World Runs on Bad Software
bkeepers
PRO
72
12k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
31
3.1k
The B2B funnel & how to create a winning content strategy
katarinadahlin
PRO
0
270
Navigating the moral maze — ethical principles for Al-driven product design
skipperchong
2
240
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
0
160
The Curse of the Amulet
leimatthew05
1
8.3k
Facilitating Awesome Meetings
lara
57
6.7k
Digital Projects Gone Horribly Wrong (And the UX Pros Who Still Save the Day) - Dean Schuster
uxyall
0
320
A designer walks into a library…
pauljervisheath
210
24k
Statistics for Hackers
jakevdp
799
230k
Transcript
fmt fmt 1
$ whoami $ whoami (id:|@)ktr_0731 サーバサイドエンジニ ア STEINS;GATE / 響け!ユーフォニア
ム 2
3
ktr0731/evans ktr0731/evans more expressive gRPC client more expressive gRPC client
4
fmt? fmt? コードフォーマッタ ソースコードを 強制的 に整形してくれ る 5
gofmt YAPF Prettier scalafmt etc. 6
gofmt を読む gofmt を読む golang/go/src/cmd/gofmt 7
前提環境 前提環境 golang/go master (157d8cfbc13fbc4c849075e905b0001fb248b5e6) 8
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go gofmtMain() gofmtMain() for i := 0; i <
flag.NArg(); i++ { path := flag.Arg(i) switch dir, err := os.Stat(path); { case err != nil: report(err) case dir.IsDir(): walkDir(path) // NOTE; call processFil default: if err := processFile(path, nil, os.St report(err) } } } 9
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go processFile() processFile() file, sourceAdj, indentAdj, err := parse(fileSet,
filename, sr if err != nil { return err } 10
cmd/gofmt/internal.go cmd/gofmt/internal.go parse() parse() parser.ParseFile file, err = parser.ParseFile(fset, filename,
psrc, parserMode) if err == nil { sourceAdj = func(src []byte, indent int) []byte { src = src[indent+len("package p\n"):] return bytes.TrimSpace(src) } 11
go/parser go/parser ParseFile() ParseFile() go/parser: 構文解析用パッケージ Go ソースコードから AST (
抽象構文木) を生 成 12
cmd/gofmt/gofmt.go cmd/gofmt/gofmt.go processFile() processFile() ast.SortImports(fileSet, file) if *simplifyAST { simplify(file)
} res, err := format(fileSet, file, sourceAdj, indentAdj, src, p if err != nil { return err } 13
cmd/gofmt/internal.go cmd/gofmt/internal.go format format var buf bytes.Buffer err := cfg.Fprint(&buf,
fset, file) if err != nil { return nil, err } return buf.Bytes(), nil 14
go/printer/printer.go go/printer/printer.go Fprint() → Fprint() → fprint() fprint() AST ノードを整形・出力するパッケージ
var p printer p.init(cfg, fset, nodeSizes) if err = p.printNode(node); err != nil { return } 15
go/printer/printer.go go/printer/printer.go printNode() printNode() switch n := node.(type) { case
ast.Expr: p.expr(n) case ast.Stmt: if _, ok := n.(*ast.LabeledStmt); ok { p.indent = 1 } p.stmt(n, false) case ast.Decl: p.decl(n) case ast.Spec: p.spec(n, 1, false) case []ast.Stmt: for _, s := range n { if _, ok := s.(*ast.LabeledStmt); ok { 16
printNode printNode AST を再帰的に辿り、 各ノードの持つ内容を整 形・出力する 17
例: 二項演算子のスペース 例: 二項演算子のスペース fmt.Println("Hello, "+"World") fmt.Println("Hello, " + "World")
18
AST AST の構造 の構造 0 *ast.CallExpr { 1 . Fun:
*ast.SelectorExpr { 2 . . X: *ast.Ident { 3 . . . NamePos: 1 4 . . . Name: "fmt" 5 . . . Obj: *ast.Object { 6 . . . . Kind: bad 7 . . . . Name: "" 8 . . . } 9 . . } 10 . . Sel: *ast.Ident { 11 . . . NamePos: 5 12 . . . Name: "Println" 13 . . } 14 . } 19
20
go/printer/printer.go go/printer/printer.go printNode() printNode() switch n := node.(type) { case
ast.Expr: p.expr(n) func (p *printer) expr(x ast.Expr) { const depth = 1 p.expr1(x, token.LowestPrec, depth) } 21
go/printer/nodes.go go/printer/nodes.go expr1() expr1() switch x := expr.(type) { case
*ast.BinaryExpr: if depth < 1 { p.internalError("depth < 1:", depth) depth = 1 } p.binaryExpr(x, prec1, cutoff(x, depth), depth) 22
go/printer/nodes.go go/printer/nodes.go binaryExpr() binaryExpr() ( 一部略) ( 一部略) // X
評価 p.expr1(x.X, prec, depth+diffPrec(x.X, prec)) if printBlank { // 追加 p.print(blank) } // "+" p.print(x.OpPos, x.Op) if printBlank { // 追加 p.print(blank) } // Y 評価 p.expr1(x.Y, prec+1, depth+1) 23
gofmt のフォーマットルール gofmt のフォーマットルール AST 生成までの過程で取り除かれるも の go/printer によって整形されるもの 24
AST AST 生成までの過程で取り除かれるもの 生成までの過程で取り除かれるもの 改行 スペー ス etc. 25
go/printer によって整形されるもの go/printer によって整形されるもの 二項演算子のスペース ( 前 述) 配列の最後の要素のカンマ etc.
[]string{"foo", "bar",} []string{"foo", "bar"} 26
似たようなのを実装してみる 似たようなのを実装してみる 27
ktr0731/markdownfmt ktr0731/markdownfmt 28
29
30
31
整形ルール 整形ルール 余計な改行・空白は取り除く テキストの最大長を 80 文字 に 32
整形ルール 整形ルール テキストの単語間のスペースは1つ に this is a text! this is
a text! 33
整形ルール 整形ルール 水平線 (hr) の上下に空 行 horizontal --- line horizontal
--- line 34
demo demo 35
これはデモ用のテキストです これはデモ用のテキストです this text is an example text for demonstration.
current version of markdownfmt accepts 80 charactors as the max width. so, maybe this text will be splitted to some lines. 36
まとめ まとめ AST なんでもできてすごい 特に Go は取得できる情報が多い AST を作れれば、フォーマットはそこまで難しく ない
意外と gofmt は読みやすい 37
参考 参考 printer - The Go Programming Language parser -
The Go Programming Language Go のための Go GitHub Flavored Markdown Spec 38