SlideShare a Scribd company logo
Go静的解析ハンズオン
The Go gopher was designed by Renee French.
The gopher stickers was made by Takuya Ueda.
Licensed under the Creative Commons 3.0
Attributions license.
2017/06/25(日)
第6回Golang勉強会
in Okinawa
1
自己紹介
メルカリ/ソウゾウ
上田拓也
twitter: @tenntenn
■ コミュニティ活動
Google Cloud Platform User Group (GCPUG) Tokyo
Goビギナーズ
golang.tokyo
Go Conference
■ 業務
GAE/Goでメルカリカウルを作ってます
GoやGCPコミュニティを盛り上げる仕事
Gopherを描く仕事(LINEスタンプ)
2
2017年7月1日(土)
BigQueryのハンズオン開催!
https://okipug.connpass.com/event/56374/
3
アジェンダ
● Goにおける静的解析の方法(復習)
● ハンズオン
○ Hello, Worldをパースしてみよう
○ 手でHello, Worldを書いてみよう
○ gopherを探せ
○ 型情報を取得みよう
4
Goにおける静的解析の方法
(ハッカーズチャンプルーの復習)
5
goパッケージ
■ 標準パッケージとして静的解析の機能を提供
go/ast 抽象構文木(AST)を提供
go/build パッケージに関する情報を集める
go/constant 定数に関する型を提供
go/doc ドキュメントをASTから取り出す
go/format コードフォーマッタの機能を提供
go/importer コンパイラに適したImporterを提供
go/parser 構文解析の機能を提供
go/printer ASTの表示機能を提供
go/scanner 字句解析の機能を提供
go/token トークンに関する型を提供
go/types 型チェックに関する機能を提供
6
静的解析の流れ
7
ソースコード
トークン
抽象構文木(AST)
型情報
構文解析
字句解析
型チェック
go/scanner
go/token
go/parser
go/ast
go/types
go/constant
字句解析 - go/scanner,go/token
■ 文字列をトークンにしていく
● 空白などを取り除き、意味のある単位=トー
クンにしていく作業
8
IDENT ADD INT
トークン
ソースコード v + 1
v + 1
構文解析 - go/parser,go/ast
■ トークンを抽象構文木(AST)にしていく
● プログラムの構造を持たせる
9
IDENT ADD INT
ソースコード
+
v 1
BinaryExpr
Ident BasicLit
トークン
抽象構文木(AST)
n := 100 + 200
m := n + 300
型チェック - go/types,go/constant
■ 抽象構文木から型に関する情報を取得する
● 識別子の解決
● 型の推論
● 定数の評価
10
定数の評価
=300
型の推論
-> int
識別子の解決
抽象構文木(AST)の取得
■ go/parserパッケージの関数を使う
● ParseExpr,ParseExprFrom
○ 式をパースする
○ ParseExprはParseExprFromを簡易版
● ParseFile
○ ファイル単位でパースする
● ParseDir
○ ディレクトリ単位でパースする
○ 中でParseFileを呼んでいる
11
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
Hello, Worldの抽象構文木の構成
12
Goの抽象構文木(AST)を手入力してHello, Worldを作る
http://qiita.com/tenntenn/items/0cbc6f1f00dc579fcd8c
Playgroundで動かす
*ast.File
[]ast.Decl
*ast.GenDecl *ast.FuncDecl
式の抽象構文木を取得する
■ 式単位を構文解析する
■ ParseExprFromでも書ける
13
expr, err := parser.ParseExpr(`v + 1`)
if err != nil {
/* エラー処理 */
}
/* exprを解析する処理 */
fset := token.NewFileSet() // ファイル情報
src := []byte(`v + 1`)
f := "" // ファイル名(式なので不要)
m := 0 // モード(式なので不要)
expr, err := parser.ParseExprFrom(fset, f, s, m)
const src = `
package main
var v = 100
func main() {
fmt.Println(v+1)
}`
fs := token.NewFileSet()
f, err := parser.ParseFile(fs, "my.go", src, 0)
if err != nil {
/* エラー処理 */
}
/* f を解析する処理 */
ソースから抽象構文木を取得する
■ Goのソースコードを構文解析する
14
引数はparse.ExprFromと
同じ構成
srcがnilだとファイル名
でファイルを開く
解析するファイルの中身
token.FileSetとは?
■ ファイル中の位置情報を記録する為の型
● 位置情報は数値で表される
● 複数のファイル間で一意の値
● 各ファイルのoffsetが記録されている
● パースする際に記録されていく
15
token.FileSetは出力引数として
Parse系の関数に渡す
*ast.BinaryExpr
*ast.Ident
*ast.BasicLit
v + 1
n, _ := parser.ParseExpr(`v + 1`)
ast.Inspect(n, func(n ast.Node) bool {
if n != nil { fmt.Printf("%Tn", n) }
return true
})
printer.Fprint(os.Stdout, token.NewFileSet(), n)
抽象構文木をトラバースする
■ ast.Inspectを使う
16
+
v 1
構文解析
抽象構文木(AST)を探索
抽象構文木(AST)を出力
BinaryExpr
Ident BasicLit
Playgroundで動かす
ast.Walkというのもある
func traverse(n ast.Node) {
switch n := n.(type) {
case *ast.Indent:
fmt.Println(n.Name)
case *ast.BinaryExpr:
traverse(n.X)
traverse(n.Y)
case *ast.UnaryExpr:
traverse(n.X)
}
}
抽象構文木をトラバースする
■ 再帰を使ってトラバースする
17
識別子の場合は名前を出力
二項演算式の場合は
各項を探索
単項演算式の場合は
項を探索
型でswitchする
Playgroundで動かす
ast.Nodeはインタフェース
参考資料
■ goパッケージで簡単に静的解析して世界を広げよう
● コードジェネレータ
○ ASTを取得する方法を調べる
○ 抽象構文木(AST)をトラバースする
○ 抽象構文木(AST)をいじってフォーマットをかける
○ Goの抽象構文木(AST)を手入力してHello, Worldを作る
○ go-app-builderのソースコードを読む
● リファクタリングツール
○ gorenameをライブラリとして使う
○ Goのスコープについて考えてみよう
○ go/typesパッケージを使い変数名をリネームしてみる
● 処理系
○ 簡単な式の評価機を作ってみる
○ 【実践goパッケージ】文字列から複素数型の値をパースする
○ もっと楽して式の評価器を作る
18
ハンズオン
19
Hello, Worldをパースしてみよう
20
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
fs := token.NewFileSet()
f, _ := parser.ParseFile(fs, "main.go", src, 0)
ast.Print(fs, f)
Playgroundで動かす
package main
import "fmt"
func main() {
fmt.Println("Hello, 世界")
}
Hello, Worldの抽象構文木を手入力
21
Goの抽象構文木(AST)を手入力してHello, Worldを作る
http://qiita.com/tenntenn/items/0cbc6f1f00dc579fcd8c
Playgroundで動かす
*ast.File
[]ast.Decl
*ast.GenDecl *ast.FuncDecl
gopherを探せ
■ ソースコードからgopherを探そう
22
type Gopher struct { gopher string `json:"gopher"` }
func main() {
const gopher = "GOPHER"
gogopher := GOPHER()
gogopher.gopher = gopher
fmt.Println(gogopher)
}
func GOPHER() (gopher *Gopher) {
gopher = &Gopher{ gopher: "gopher" }
return
}
https://gist.github.com/tenntenn/ca92384795133b3ec5de0e0d7de5eec5
型チェックをしてみよう
■ 例:int型の変数を探す
23
cfg := &types.Config{Importer: importer.Default()}
info := &types.Info{
Defs: map[*ast.Ident]types.Object{},
}
cfg.Check("main", fs, []*ast.File{f}, info)
it := types.Universe.Lookup("int").Type()
for idnt, o := range info.Defs {
if o != nil &&
types.Identical(o.Type(), it) {
fmt.Println(fs.Position(idnt.Pos()), idnt)
}
}
https://gist.github.com/tenntenn/706d73e0d82105b0d25179578b953745
型チェックをしてみよう
■ 構造体型のgopherを探そう
24
type Gopher struct { gopher string `json:"gopher"` }
func main() {
const gopher = "GOPHER"
gogopher := GOPHER()
gogopher.gopher = gopher
fmt.Println(gogopher)
}
func GOPHER() (gopher *Gopher) {
gopher = &Gopher{ gopher: "gopher" }
return
}
Thank you!
twitter: @tenntenn
Qiita: tenntenn
connpass: tenntenn
25

More Related Content

PDF
Java 8 features
PDF
Java8 features
PDF
Dependency Injection
PDF
PHP unserialization vulnerabilities: What are we missing?
PDF
Go1.18 Genericsを試す
PDF
Form認証で学ぶSpring Security入門
PPTX
Interfaces in java
PDF
オブジェクト指向できていますか?
Java 8 features
Java8 features
Dependency Injection
PHP unserialization vulnerabilities: What are we missing?
Go1.18 Genericsを試す
Form認証で学ぶSpring Security入門
Interfaces in java
オブジェクト指向できていますか?

What's hot (20)

PDF
OpenAPI development with Python
PPT
Java exception
PPTX
OOP Introduction with java programming language
PPTX
C# classes objects
PDF
Mavenの真実とウソ
PDF
Testing with JUnit 5 and Spring
PDF
Lambda and Stream Master class - part 1
PPTX
C# Inheritance
PPTX
Asp.NET Validation controls
PDF
CLASS & OBJECT IN JAVA
PPTX
Factory Method Pattern
PDF
Redmineの画面をあなた好みにカスタマイズ - View customize pluginの紹介 - Redmine Japan 2020
ODP
Java 9 Features
ODP
PPTX
LINQ in C#
KEY
Go言語のスライスを理解しよう
PPTX
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
PDF
Tackling Complexity
PDF
業務で使うIRC
OpenAPI development with Python
Java exception
OOP Introduction with java programming language
C# classes objects
Mavenの真実とウソ
Testing with JUnit 5 and Spring
Lambda and Stream Master class - part 1
C# Inheritance
Asp.NET Validation controls
CLASS & OBJECT IN JAVA
Factory Method Pattern
Redmineの画面をあなた好みにカスタマイズ - View customize pluginの紹介 - Redmine Japan 2020
Java 9 Features
LINQ in C#
Go言語のスライスを理解しよう
Java Spring framework, Dependency Injection, DI, IoC, Inversion of Control
Tackling Complexity
業務で使うIRC
Ad

Viewers also liked (20)

PDF
Cloud Functionsの紹介
PDF
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
PDF
条件式評価器の実装による管理ツールの抽象化
PDF
粗探しをしてGoのコントリビューターになる方法
PDF
Goにおける静的解析と製品開発への応用
PDF
GoによるiOSアプリの開発
PPTX
うしちゃん WebRTC Chat on SkyWayの開発コードw
PDF
goパッケージで型情報を用いたソースコード検索を実現する
PDF
Static Analysis in Go
PDF
HTTP2 RFC 発行記念祝賀会
PDF
Mobile Apps by Pure Go with Reverse Binding
PDF
Go1.8 for Google App Engine
PDF
Namespace API を用いたマルチテナント型 Web アプリの実践
PDF
Javaトラブルに備えよう #jjug_ccc #ccc_h2
PDF
Cloud functionsの紹介
PDF
メルカリ・ソウゾウでは どうGoを活用しているのか?
PDF
HTTP2 時代の Web - web over http2
PDF
Google Assistant関係のセッションまとめ
PDF
オススメの標準・準標準パッケージ20選
PPTX
WebRTC Browsers n Stacks Implementation differences
Cloud Functionsの紹介
静的解析とUIの自動生成を駆使してモバイルアプリの運用コストを大幅に下げた話
条件式評価器の実装による管理ツールの抽象化
粗探しをしてGoのコントリビューターになる方法
Goにおける静的解析と製品開発への応用
GoによるiOSアプリの開発
うしちゃん WebRTC Chat on SkyWayの開発コードw
goパッケージで型情報を用いたソースコード検索を実現する
Static Analysis in Go
HTTP2 RFC 発行記念祝賀会
Mobile Apps by Pure Go with Reverse Binding
Go1.8 for Google App Engine
Namespace API を用いたマルチテナント型 Web アプリの実践
Javaトラブルに備えよう #jjug_ccc #ccc_h2
Cloud functionsの紹介
メルカリ・ソウゾウでは どうGoを活用しているのか?
HTTP2 時代の Web - web over http2
Google Assistant関係のセッションまとめ
オススメの標準・準標準パッケージ20選
WebRTC Browsers n Stacks Implementation differences
Ad

Similar to Go静的解析ハンズオン (20)

PDF
静的解析を使った開発ツールの開発
PDF
マスター・オブ・goパッケージ
PDF
Goでかんたんソースコードの静的解析
PDF
エディタの壁を越えるGoの開発ツールの文化と作成法
PDF
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
PDF
エキスパートGo
PDF
Gopher Fest 2017参加レポート
PDF
TechDo Goハンズオン#3
PDF
Go入門
PDF
GitHub での Haskell の色が変わったんで
PDF
Goとテスト
PDF
Goで言語処理系(の途中まで)を作ろう
PDF
今日から始めるGopher - スタートGo #0 @GDG名古屋
PDF
Cookpad Summer Intern 2015 - Programming Paradigm
PDF
PCさえあればいい。
PDF
認証Gwのプロトタイプでgolang使ってみた20171024
PDF
初心者向けGo言語勉強会
PDF
ErlangでErlagVM上で動く言語の作り方
PDF
Go Friday 傑作選
PPTX
Go guide for Java programmer
静的解析を使った開発ツールの開発
マスター・オブ・goパッケージ
Goでかんたんソースコードの静的解析
エディタの壁を越えるGoの開発ツールの文化と作成法
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
エキスパートGo
Gopher Fest 2017参加レポート
TechDo Goハンズオン#3
Go入門
GitHub での Haskell の色が変わったんで
Goとテスト
Goで言語処理系(の途中まで)を作ろう
今日から始めるGopher - スタートGo #0 @GDG名古屋
Cookpad Summer Intern 2015 - Programming Paradigm
PCさえあればいい。
認証Gwのプロトタイプでgolang使ってみた20171024
初心者向けGo言語勉強会
ErlangでErlagVM上で動く言語の作り方
Go Friday 傑作選
Go guide for Java programmer

More from Takuya Ueda (9)

PDF
Goにおけるバージョン管理の必要性 − vgoについて −
PDF
WebAssembly with Go
PDF
GAE/Goとsyncパッケージ
PDF
そうだ、Goを始めよう
PDF
メルカリ カウルのマスタデータの更新
PDF
Goでwebアプリを開発してみよう
PDF
GAE/GoでWebアプリ開発入門
PDF
GAE/GoでLINE Messaging API を使う
PDF
メルカリアッテの実務で使えた、GAE/Goの開発を効率的にする方法
Goにおけるバージョン管理の必要性 − vgoについて −
WebAssembly with Go
GAE/Goとsyncパッケージ
そうだ、Goを始めよう
メルカリ カウルのマスタデータの更新
Goでwebアプリを開発してみよう
GAE/GoでWebアプリ開発入門
GAE/GoでLINE Messaging API を使う
メルカリアッテの実務で使えた、GAE/Goの開発を効率的にする方法

Go静的解析ハンズオン