Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Goにおける静的解析と製品開発への応用

1,618 views

Published on

ハッカーズチャンプルー2017 カンファレンス部で発表した資料です。

Published in: Technology
  • Hi there! I just wanted to share a list of sites that helped me a lot during my studies: .................................................................................................................................... www.EssayWrite.best - Write an essay .................................................................................................................................... www.LitReview.xyz - Summary of books .................................................................................................................................... www.Coursework.best - Online coursework .................................................................................................................................... www.Dissertations.me - proquest dissertations .................................................................................................................................... www.ReMovie.club - Movies reviews .................................................................................................................................... www.WebSlides.vip - Best powerpoint presentations .................................................................................................................................... www.WritePaper.info - Write a research paper .................................................................................................................................... www.EddyHelp.com - Homework help online .................................................................................................................................... www.MyResumeHelp.net - Professional resume writing service .................................................................................................................................. www.HelpWriting.net - Help with writing any papers ......................................................................................................................................... Save so as not to lose
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here

Goにおける静的解析と製品開発への応用

  1. 1. 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/24(土) ハッカーズチャンプルー 2017 1
  2. 2. 自己紹介 メルカリ/ソウゾウ 上田拓也 twitter: @tenntenn ■ コミュニティ活動 Google Cloud Platform User Group (GCPUG) Tokyo Goビギナーズ golang.tokyo Go Conference ■ 業務 GAE/Goでメルカリカウルを作ってます GoやGCPコミュニティを盛り上げる仕事 Gopherを描く仕事(LINEスタンプ) 2
  3. 3. 2017年7月1日(土) BigQueryのハンズオン開催! https://okipug.connpass.com/event/56374/ 3
  4. 4. アジェンダ ● 静的解析とは? ● Goにおける静的解析の方法 ● 静的解析の製品開発への応用 ○ gpath, go-httpdoc ○ バナーツール 4
  5. 5. 静的解析とは? 5
  6. 6. 静的解析と動的解析 ■ 静的解析 ● プログラムを実行せずに解析すること ● ソースコードを解析する ● 例:lint, コード補完, コードフォーマッタ ■ 動的解析 ● プログラムを実行して解析すること ● 実行時の変数の状態や関数の実行順などを検証 ● 例:レースディテクション 6
  7. 7. 静的解析とリフレクション ■ リフレクション ● 実行時に型や値の情報を解析する ■ Goのリフレクション ● reflectパッケージを使う ● 実行時にstructタグにアクセス唯一の方法 ● 任意の型に値を入れたりする ● JSONやXMLなどのエンコーディングに使われる 7
  8. 8. 静的解析とGoの開発ツール ■ Goは静的解析を開発ツールに使う事が多い ● gofmt/goimports ○ コードフォーマッター ● go vet/golint ○ コードチェッカー、リンター ● guru ○ 静的解析 ● gocode ○ コード補完 ● errcheck ○ エラー処理のチェック ● gorename/gomvpkg ○ リファクタリングツール 8
  9. 9. Goと静的解析 ■ Goは静的解析がしやすい言語 ● 静的型付け言語 ● 文法がシンプル ● 暗黙の型変換がない ● 型推論 ● 標準パッケージで静的解析機能を提供 9 静的解析でも多くの事が知れる
  10. 10. 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 型チェックに関する機能を提供 10
  11. 11. Goにおける静的解析の方法 11
  12. 12. 静的解析の流れ 12 ソースコード トークン 抽象構文木(AST) 型情報 構文解析 字句解析 型チェック go/scanner go/token go/parser go/ast go/types go/constant
  13. 13. 字句解析 - go/scanner,go/token ■ 文字列をトークンにしていく ● 空白などを取り除き、意味のある単位=トー クンにしていく作業 13 IDENT ADD INT トークン ソースコード v + 1
  14. 14. v + 1 構文解析 - go/parser,go/ast ■ トークンを抽象構文木(AST)にしていく ● プログラムの構造を持たせる 14 IDENT ADD INT ソースコード + v 1 BinaryExpr Ident BasicLit トークン 抽象構文木(AST)
  15. 15. n := 100 + 200 m := n + 300 型チェック - go/types,go/constant ■ 抽象構文木から型に関する情報を取得する ● 識別子の解決 ● 型の推論 ● 定数の評価 15 定数の評価 =300 型の推論 -> int 識別子の解決
  16. 16. 抽象構文木(AST)の取得 ■ go/parserパッケージの関数を使う ● ParseExpr,ParseExprFrom ○ 式をパースする ○ ParseExprはParseExprFromを簡易版 ● ParseFile ○ ファイル単位でパースする ● ParseDir ○ ディレクトリ単位でパースする ○ 中でParseFileを呼んでいる 16
  17. 17. package main import "fmt" func main() { fmt.Println("Hello, 世界") } Hello, Worldの抽象構文木の構成 17 Goの抽象構文木(AST)を手入力してHello, Worldを作る http://qiita.com/tenntenn/items/0cbc6f1f00dc579fcd8c Playgroundで動かす *ast.File []ast.Decl *ast.GenDecl *ast.FuncDecl
  18. 18. 式の抽象構文木を取得する ■ 式単位を構文解析する ■ ParseExprFromでも書ける 18 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)
  19. 19. 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のソースコードを構文解析する 19 引数はparse.ExprFromと 同じ構成 srcがnilだとファイル名 でファイルを開く 解析するファイルの中身
  20. 20. token.FileSetとは? ■ ファイル中の位置情報を記録する為の型 ● 位置情報は数値で表される ● 複数のファイル間で一意の値 ● 各ファイルのoffsetが記録されている ● パースする際に記録されていく 20 token.FileSetは出力引数として Parse系の関数に渡す
  21. 21. *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を使う 21 + v 1 構文解析 抽象構文木(AST)を探索 抽象構文木(AST)を出力 BinaryExpr Ident BasicLit Playgroundで動かす ast.Walkというのもある
  22. 22. 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) } } 抽象構文木をトラバースする ■ 再帰を使ってトラバースする 22 識別子の場合は名前を出力 二項演算式の場合は 各項を探索 単項演算式の場合は 項を探索 型でswitchする Playgroundで動かす ast.Nodeはインタフェース
  23. 23. 参考資料 ■ goパッケージで簡単に静的解析して世界を広げよう ● コードジェネレータ ○ ASTを取得する方法を調べる ○ 抽象構文木(AST)をトラバースする ○ 抽象構文木(AST)をいじってフォーマットをかける ○ Goの抽象構文木(AST)を手入力してHello, Worldを作る ○ go-app-builderのソースコードを読む ● リファクタリングツール ○ gorenameをライブラリとして使う ○ Goのスコープについて考えてみよう ○ go/typesパッケージを使い変数名をリネームしてみる ● 処理系 ○ 簡単な式の評価機を作ってみる ○ 【実践goパッケージ】文字列から複素数型の値をパースする ○ もっと楽して式の評価器を作る 23
  24. 24. 静的解析の製品開発への応用 例1:gpath, go-httpdoc 24
  25. 25. go-httpdoc 25 ■ テストからAPIドキュメントを生成する ● https://github.com/mercari/go-httpdoc ● HTTPハンドラのテストから生成 ● リクエストやレスポンスが記載される ● gRPCやJSON RPCなAPIでも利用可能
  26. 26. リクエスト/レスポンスのテスト ■ リクエストのテストからドキュメントを生成 ● Request Bodyをリフレクションでテストしている ● 構造体の任意のフィールドを指定できる 26 validator.RequestBody(t, []httpdoc.TestCase{ {"Name", "tenntenn", "User Name"}, {"Attribute.Birthday", "1986-01-12", "User birthday YYYY-MM-DD format"}, }, &createUserRequest{}) 参考:go-httpdocのexample
  27. 27. tenntenn/gpath ■ 構造体の任意のフィールドにアクセスできる ● https://github.com/tenntenn/gpath ● 複雑なリフレクションが簡単に書ける ● Goの式で記述できる ● スライスやマップにも対応している 27 type Bar struct { N []int } type Foo struct { Bar *Bar } f := &Foo{ Bar: &Bar{ N: []int{100} }} v, _ := At(f, `Bar.N[0]`) fmt.Println(v)
  28. 28. 開発ツールへ静的解析を使う ■ 21世紀なので自動化できるものは自動化する ● APIドキュメントの生成 ● コードジェネレータ ● よくあるバグの指摘 ○ go vetのプロジェクトカスタマイズ版 ○ エラーの再代入 ○ コンテキストの使い回し ○ structタグのミス 28 静的解析を用いて自作しよう
  29. 29. tenntenn/goq ■ Goの抽象構文木を簡単に検索できる ● https://github.com/tenntenn/goq ● 検索クエリを作ることができる ● 複雑な検索ができる 29 t := types.Universe.Lookup("error").Type() errType := t.Underlying().(*types.Interface) q := &goq.Type{ Identical: errType, } results := goq.New(fset, files, info).Query(q) 例:型がerrorのものだけ抽出
  30. 30. 静的解析の製品開発への応用 例2:バナーツール 30
  31. 31. バナーツール ■ バナーの入稿を管理するツール ● 式で配信条件を設定 ● 1ソースで複数の環境に対応 31
  32. 32. バナーツール ■ バナーの入稿を管理するツール ● 式で配信条件を設定 ● 1ソースで複数の環境に対応 32 バナーツール ・配信条件 ・レスポンス バナー取得 OS, APIバージョン などの変数 条件に当てはまるバナー 画像URL, 遷移先URL アプリ
  33. 33. デモ 33 YouTubeで見る
  34. 34. 配信条件式の評価 ■ バナーの配信条件に条件式を用いる ● Goの式としてパースできる独自形式 ● 型定義を式で表現できるようにしてある 34 バナー取得 GET /banner/?os=1 String(os) == "1" バナー画像URL 配信条件: バナーツール
  35. 35. 条件式からUIの自動生成 ■UIを自動生成し簡単に入力できるにする ● 条件式からJSON Schemaを生成する ● JSON EditorでJSON SchemaからWeb UIを生成 35 os: iOS ▼ Android UIを生成する部分 リクエストから もらう部分 ※一部簡略化している 生成したWeb UI String(os) == Enum(__os, "0,1", "iOS,Android") String(os) == "1" UIで入力した値を式へ展開
  36. 36. 静的解析を採用した効果 ■ 1ソースで複数アプリに展開 ● 4つ以上のアプリで採用 ● バナー配信以外にも使える ■ 条件式からUIを自動生成 ● アプリごとに高いカスタマイズ性を提供 ● 非エンジニアでも利用可能 36
  37. 37. まとめ ■ Goは静的解析に向いている ● 静的型付け言語 ● 標準パッケージで対応 ■ 静的解析を開発ツールに使う ● よくあるレビュー指摘事項を自動化する ● 自作go vetやlintを作る ■ 開発ツール以外にも使える ● うまく使えば本番で稼働するコードも書ける ● 式としてパースできるのは強い 37
  38. 38. 38 第6回Golang勉強会 in Okinawa ハッカーズチャンプルー2017後夜祭 https://okinawa-go.doorkeeper.jp/events/61119
  39. 39. Thank you! twitter: @tenntenn Qiita: tenntenn connpass: tenntenn 39

×