SlideShare a Scribd company logo
1 of 43
Download to read offline
GoのASTをいじくって
新しいツールを作る
わかめ まさひろ
わかめ まさひろ @vvakame
TypeScript
Masahiro Wakame
DefinitelyTyped
appengine
photo from golang.org/doc/gopher/
めんどいことはしたくない
誰だってそうする
俺だってそうする
encoding/json
play.golang.org/p/T9uO25D2xz
…


type Game struct {

ID int64 `json:"id"`

Title string `json:"title"`

Price int `json:"price"`

InDevelopment bool `json:"inDevelopment"`

ShippedAt time.Time `json:"shippedAt"`

}



func main() {

game := &Game{

ID: 1,

Title: "Splatoon",

Price: 5700,

InDevelopment: false,

}

b, _ := json.Marshal(game)

fmt.Println(string(b))

}
encoding/json
…


type Game struct {

ID int64 `json:"id"`

Title string `json:"title"`

Price int `json:"price"`

InDevelopment bool `json:"inDevelopment"`

ShippedAt time.Time `json:"shippedAt"`

}



func main() {

game := &Game{

ID: 1,

Title: "Splatoon",

Price: 5700,

InDevelopment: false,

}

b, _ := json.Marshal(game)

fmt.Println(string(b))

}
手書き!?
正気か!?!?
めんどい
“ 閉じるの忘れる
typoる
jwg 作った
//go:generate jwg -output model_json.go .

package sample



…


// +jwg

type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}



func main() {

game := &Game{

ID: 1, Title: "Splatoon", Price: 5700, InDevelopment: false,

}

jsonObj, _ := NewGameJsonBuilder().AddAll().Convert(game)

b, _ := json.Marshal(jsonObj)

fmt.Println(string(b))

}
jwg = Json Wrapper Generator
//go:generate jwg -output model_json.go .

package sample



…


// +jwg

type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}



func main() {

game := &Game{

ID: 1, Title: "Splatoon", Price: 5700, InDevelopment: false,

}

jsonObj, _ := NewGameJsonBuilder().AddAll().Convert(game)

b, _ := json.Marshal(jsonObj)

fmt.Println(string(b))

}
go generate 使う!
コメントにタグ書く(標準仕様などない!
生成したコード利用だ!
jwg 作った
自動生成!
type GameJson struct {

ID int64 `json:"id,omitempty"`

Title string `json:"title,omitempty"`

Price int `json:"price,omitempty"`

InDevelopment bool `json:"inDevelopment,omitempty"`

ShippedAt time.Time `json:"shippedAt,omitempty"`

}
楽
その他!
type GameJson
func (orig *GameJson) Convert() (*Game, error)
type GameJsonBuilder
func NewGameJsonBuilder() *GameJsonBuilder
func (b *GameJsonBuilder) Add(info *GamePropertyInfo) *GameJsonBuilder
func (b *GameJsonBuilder) AddAll() *GameJsonBuilder
func (b *GameJsonBuilder) Convert(orig *Game) (*GameJson, error)
func (b *GameJsonBuilder) ConvertList(orig []*Game) (GameJsonList, error)
func (b *GameJsonBuilder) Marshal(orig *Game) ([]byte, error)
func (b *GameJsonBuilder) Remove(info *GamePropertyInfo) *GameJsonBuilder
type GameJsonList
func (jsonList GameJsonList) Convert() ([]*Game, error)
type GamePropertyDecoder
type GamePropertyEncoder
type GamePropertyInfo *JsonBuilder
*Property(De|En)coder
*PropertyInfo
Web API作成用
play.golang.org/p/5wYA62Njvn
func (b *GameJsonBuilder) AddSite() *GameJsonBuilder {

b.AddAll()

b.Remove(b.ID) // IDは内部情報なのでいらない

b.Price.Encoder = func(src *Game, dest *GameJson) error {

if !src.InDevelopment {

dest.Price = src.Price // 開発中じゃない時だけ価格を出すよ!

}

return nil

}



return b

}



func main() {

game := &Game{

ID: 2, Title: "Secret of Yaba", Price: 9999, InDevelopment: true,

}

jsonObj, _ := NewGameJsonBuilder().AddSite().Convert(game)

b, _ := json.Marshal(jsonObj)

fmt.Println(string(b))

}
{
"title":"Secret of Yaba”,
“inDevelopment":true,
“shippedAt":"0001-01-01T00:00:00Z"
}
実行結果→
この間公開しました!
生成コードは特に依存なし
みんなも作ろう!
主張
• コード生成 is 便利
• GoだとGenericsないしコード増えがち
• コンパイル時チェックの恩恵!
• 文字列で指定とか時代遅れだよね∼
• 元コード→データ化→加工→生成!
• まずはソースコードを解析しないと!
正規表現で頑張る
http://play.golang.org/p/fsOl7CcjgB
package main



import (

"fmt"

"regexp"

)



func main() {

code := `

type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}

`



re:=regexp.MustCompile(`s*types+([a-zA-Z]+)s+structs+{n(?:s*([a-zA-Z0-9]+)s+([a-zA-Z0-9.]+)s*n)*s*}`)

result := re.FindAllStringSubmatch(code,-1)

fmt.Printf("%#v", result)

}
copyright @shati_ko
ASTを活用する
• AST = Abstract Syntax Tree
• 本来はコンパイラ内部の中間表現
• ソースコードをデータとして使える!
• コード解析はライブラリに任せよう!
• 解析後のコード組立に専念できる!
copyright @shati_ko
AST? コード生成??
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
type (

A struct {

Foo string

}

B struct {

Bar string

}

)
こういう記法もある(怖い
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
ast.Ident
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
ast.Ident
ast.StructType
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
ast.Ident
ast.StructType
ast.FieldList
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
ast.Ident
ast.StructType
ast.FieldList
ast.Field type A struct {

Foo, Bar string

}
こういう記法もある(怖い
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
ast.Ident
ast.StructType
ast.FieldList
ast.Field
ast.Ident
Game struct → AST
type Game struct {

ID int64

Title string

Price int

InDevelopment bool

ShippedAt time.Time

}
ast = go/ast package
ast.GenDecl
ast.TypeSpec
ast.Ident
ast.StructType
ast.FieldList
ast.Field
ast.Ident
ast.Ident
AST→コード生成
_人人人人人人人人人人人人_
> 文字列組み立て頑張る <
 ̄Y^Y^Y^Y^Y^Y^Y^Y^Y^Y^Y ̄
まじか
まじだ
開発のコツと構造
ここでは、struct読み取り→
ラッパ生成の流れに絞って解説する
ツール開発の流れ
1. 処理対象(のstruct)を決める
2. コード生成結果を手書きする
•名前を機械的に考えてつけよう
3. 必要な俺形式のデータ構造を設計する
•ASTから取れるか?不足はないか?
•型情報取れなくて辛いパターンある
4. 頑張ってAST取って変換して生成処理書く
Goコードの構造
// generated by jwg -output model_json.go .; DO NOT EDIT



package sample



import (

"encoding/json"

"time"

)



// for Game

type GameJson struct {

ID int64 `json:"id,omitempty"`

Title string `json:"title,omitempty"`

Price int `json:"price,omitempty"`

InDevelopment bool `json:"inDevelopment,omitempty"`

ShippedAt time.Time `json:"shippedAt,omitempty"`

}

PackageClause
ImportDecl
TopLevelDecl
俺形式が必要な理由
// generated by jwg -output model_json.go .; DO NOT EDIT



package sample



import (

"encoding/json"

"time"

)



// for Game

type GameJson struct {

ID int64 `json:"id,omitempty"`

Title string `json:"title,omitempty"`

Price int `json:"price,omitempty"`

InDevelopment bool `json:"inDevelopment,omitempty"`

ShippedAt time.Time `json:"shippedAt,omitempty"`

}

正しいPackageClauseの生成には、
TopLevelDecl生成結果の把握が必要! etc..
代表的な俺形式
• Source (生成結果ソース全体)
• Struct (生成するstruct1個分)
• Field (↑のfield1個分)
• Tag (↑に付属するtag情報)
jwgの場合
// BuildStruct represents source code of assembling..

type BuildSource struct {

g *genbase.Generator

pkg *genbase.PackageInfo

typeInfos genbase.TypeInfos



Structs []*BuildStruct

}



// BuildStruct represents struct of assembling..

type BuildStruct struct {

parent *BuildSource

typeInfo *genbase.TypeInfo



Fields []*BuildField

}



// BuildField represents field of BuildStruct.

type BuildField struct {

parent *BuildStruct

fieldInfo *genbase.FieldInfo



Name string

Embed bool

Tag *BuildTag

}



// BuildTag represents tag of BuildField.

type BuildTag struct {

field *BuildField



Name string

Ignore bool // e.g. Secret string `json:"-"`

DoNotEmit bool // e.g. Field int `json:",omitempty"`

String bool // e.g. Int64String int64 `json:",string"`

}
genbaseのご紹介
• 3つほどコード生成ツール作った
• 定形処理の存在に気がつく
• AST読み込み
• 指定されたorタグ付きstructの収集
• import句の管理
• コード組み立て・フォーマット
• その他便利関数とか
github.com/favclip/genbase
参考:typewriter
そして気合
func (st *BuildStruct) emit(g *genbase.Generator) error {

g.Printf("// for %sn", st.Name())



// generate FooJson struct from Foo struct

g.Printf("type %sJson struct {n", st.Name())

for _, field := range st.Fields {

if field.Tag.Ignore {

continue

}

postfix := ""

if field.WithJWG() {

postfix = "Json"

}

tagString := field.Tag.TagString()

if tagString != "" {

tagString = fmt.Sprintf("`%s`", tagString)

}

if field.Embed {

g.Printf("%s%s %sn", field.fieldInfo.TypeName(), postfix, tagString)

} else {

g.Printf("%s %s%s %sn", field.Name, field.fieldInfo.TypeName(), postfix, tagString)

}

}

g.Printf("}nn")



g.Printf("type %[1]sJsonList []*%[1]sJsonnn", st.Name())



// generate property builder

g.Printf("type %[1]sPropertyEncoder func(src *%[1]s, dest *%[1]sJson) errornn", st.Name())

g.Printf("type %[1]sPropertyDecoder func(src *%[1]sJson, dest *%[1]s) errornn", st.Name())



// generate property info

g.Printf(`

type %[1]sPropertyInfo struct {

name string

Encoder %[1]sPropertyEncoder

Decoder %[1]sPropertyDecoder

}



`, st.Name())



// generate json builder

↓ざっくり500行続く
デカさ
• genbase
• ざっくり580行くらい
• jwg
• ざっくり850行くらい
• 生成後コード読んでから読めば理解る
• …んじゃないかな多分
Tips
• 埋め込みstructは敵
• 生成すべきコードがどんどん複雑に…
• fieldの型がstructだと絶望
• ASTだけでは型の詳細な情報がない
• 生成コードないとコンパイル通らん
• Printfの %[1]s 記法マジ便利
I ♥ Pull Request
• よりGoらしい書き方できるよ!
• より効率の良い実装があるよ!
• Template使えよ!
• text/template は気に入らなかった…
• なんかないですかね?
github.com/favclip
宣伝
We are hiring!
• 開発:テレビ朝日
• jwg, genbase 他 爆誕!
• http://www.favclip.com/
• appengine/go開発者絶賛募集中!
Goに対する感想
疑問
• ライブラリのリビジョン?
• jwg 非互換な変更していいのかしら
• embedしたstructのメソッド呼び奴
• 外側のstructがreceiverになってほし
• Generics欲しい気持ちが抑えられない
怒り💢
• stringのslice取ると[]byteなのやめて💢
• 1文字=1バイトマンが作るライブラリ
• 再帰的なパッケージ参照許して💢
• 1パッケージが際限なくでかくなる…
• err != nil 毎回やるのだるい💢

More Related Content

What's hot

ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPCZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPCYoshifumi Kawai
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...Yoshifumi Kawai
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#信之 岩永
 
Scripting Layer for Android + Perl
Scripting Layer for Android + PerlScripting Layer for Android + Perl
Scripting Layer for Android + PerlNaoya Ito
 
Swiftのアプリ開発でハマったこと
Swiftのアプリ開発でハマったことSwiftのアプリ開発でハマったこと
Swiftのアプリ開発でハマったことyohei sugigami
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)信之 岩永
 
Titanium Mobile
Titanium MobileTitanium Mobile
Titanium MobileNaoya Ito
 
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexprGenya Murakami
 
SEH on mingw32
SEH on mingw32SEH on mingw32
SEH on mingw32kikairoya
 
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法Yoshifumi Kawai
 
Hacking Ruby with Python
Hacking Ruby with PythonHacking Ruby with Python
Hacking Ruby with PythonTaisuke Yamada
 
Async design with Unity3D
Async design with Unity3DAsync design with Unity3D
Async design with Unity3DKouji Hosoda
 
基礎からのCode Contracts
基礎からのCode Contracts基礎からのCode Contracts
基礎からのCode ContractsYoshifumi Kawai
 
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリームC# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム信之 岩永
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexprGenya Murakami
 
Cプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧めCプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧めMITSUNARI Shigeo
 

What's hot (20)

ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPCZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
 
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
 
.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#.NET Core 2.x 時代の C#
.NET Core 2.x 時代の C#
 
Scripting Layer for Android + Perl
Scripting Layer for Android + PerlScripting Layer for Android + Perl
Scripting Layer for Android + Perl
 
Swiftのアプリ開発でハマったこと
Swiftのアプリ開発でハマったことSwiftのアプリ開発でハマったこと
Swiftのアプリ開発でハマったこと
 
C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)C# 8.0 Preview in Visual Studio 2019 (16.0)
C# 8.0 Preview in Visual Studio 2019 (16.0)
 
Titanium Mobile
Titanium MobileTitanium Mobile
Titanium Mobile
 
中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr中3女子が狂える本当に気持ちのいい constexpr
中3女子が狂える本当に気持ちのいい constexpr
 
SEH on mingw32
SEH on mingw32SEH on mingw32
SEH on mingw32
 
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
 
Node native ext
Node native extNode native ext
Node native ext
 
Hacking Ruby with Python
Hacking Ruby with PythonHacking Ruby with Python
Hacking Ruby with Python
 
Unityで覚えるC#
Unityで覚えるC#Unityで覚えるC#
Unityで覚えるC#
 
Rx java x retrofit
Rx java x retrofitRx java x retrofit
Rx java x retrofit
 
Inside FastEnum
Inside FastEnumInside FastEnum
Inside FastEnum
 
Async design with Unity3D
Async design with Unity3DAsync design with Unity3D
Async design with Unity3D
 
基礎からのCode Contracts
基礎からのCode Contracts基礎からのCode Contracts
基礎からのCode Contracts
 
C# 8.0 非同期ストリーム
C# 8.0 非同期ストリームC# 8.0 非同期ストリーム
C# 8.0 非同期ストリーム
 
中3女子でもわかる constexpr
中3女子でもわかる constexpr中3女子でもわかる constexpr
中3女子でもわかる constexpr
 
Cプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧めCプログラマのためのカッコつけないプログラミングの勧め
Cプログラマのためのカッコつけないプログラミングの勧め
 

Similar to GoCon 2015 Summer GoのASTをいじくって新しいツールを作る

Ember.js Tokyo event 2014/09/22 (Japanese)
Ember.js Tokyo event  2014/09/22 (Japanese)Ember.js Tokyo event  2014/09/22 (Japanese)
Ember.js Tokyo event 2014/09/22 (Japanese)Yuki Shimada
 
JSON Value into Power Automate
JSON Value into Power AutomateJSON Value into Power Automate
JSON Value into Power AutomateTomoyuki Obi
 
node+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作るnode+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作るKiyoshi SATOH
 
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会Jumpei Ogawa
 
Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)
Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)
Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)Google Developer Relations Team
 
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和schoowebcampus
 
どこでも動くゲームを作るためのベタープラクティス
どこでも動くゲームを作るためのベタープラクティスどこでも動くゲームを作るためのベタープラクティス
どこでも動くゲームを作るためのベタープラクティス5mingame2
 
enchant.js meetup Tokyo vol.2 Tutorial
enchant.js meetup Tokyo vol.2 Tutorialenchant.js meetup Tokyo vol.2 Tutorial
enchant.js meetup Tokyo vol.2 TutorialRyo Shimizu
 
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜勝成 鈴江
 
2012 03-03-titanium plusquicktigame2d
2012 03-03-titanium plusquicktigame2d2012 03-03-titanium plusquicktigame2d
2012 03-03-titanium plusquicktigame2dHiroshi Oyamada
 
Unity C#3からC#6に向けて
Unity C#3からC#6に向けてUnity C#3からC#6に向けて
Unity C#3からC#6に向けてonotchi_
 
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするKiyoshi Sawada
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトKiyoshi Sawada
 
CodeIgniterによるPhwittr
CodeIgniterによるPhwittrCodeIgniterによるPhwittr
CodeIgniterによるPhwittrkenjis
 
TypeScript と Visual Studio Code
TypeScript と Visual Studio CodeTypeScript と Visual Studio Code
TypeScript と Visual Studio CodeAkira Inoue
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)fisuda
 
PGCon.jp 2014 jsonb-datatype-20141205
PGCon.jp 2014 jsonb-datatype-20141205PGCon.jp 2014 jsonb-datatype-20141205
PGCon.jp 2014 jsonb-datatype-20141205Toshi Harada
 
Creators'night#14今井
Creators'night#14今井Creators'night#14今井
Creators'night#14今井Daisuke Imai
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)fisuda
 

Similar to GoCon 2015 Summer GoのASTをいじくって新しいツールを作る (20)

Ember.js Tokyo event 2014/09/22 (Japanese)
Ember.js Tokyo event  2014/09/22 (Japanese)Ember.js Tokyo event  2014/09/22 (Japanese)
Ember.js Tokyo event 2014/09/22 (Japanese)
 
Arctic.js
Arctic.jsArctic.js
Arctic.js
 
JSON Value into Power Automate
JSON Value into Power AutomateJSON Value into Power Automate
JSON Value into Power Automate
 
node+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作るnode+socket.io+enchant.jsでチャットゲーを作る
node+socket.io+enchant.jsでチャットゲーを作る
 
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
QML を用いた YouTube クライアントの作成 - 関東 Qt 勉強会
 
Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)
Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)
Google Developer Day 2010 Japan: Android でリアルタイムゲームを開発する方法: リベンジ (クリス プルエット)
 
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
ノンプログラマーでも明日から使えるJavaScript簡単プログラム 先生:柳井 政和
 
どこでも動くゲームを作るためのベタープラクティス
どこでも動くゲームを作るためのベタープラクティスどこでも動くゲームを作るためのベタープラクティス
どこでも動くゲームを作るためのベタープラクティス
 
enchant.js meetup Tokyo vol.2 Tutorial
enchant.js meetup Tokyo vol.2 Tutorialenchant.js meetup Tokyo vol.2 Tutorial
enchant.js meetup Tokyo vol.2 Tutorial
 
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
C++でのゲームプログラミングをしたときのお話 札幌C++勉強会 #4 〜スタートゲームプログラミング〜
 
2012 03-03-titanium plusquicktigame2d
2012 03-03-titanium plusquicktigame2d2012 03-03-titanium plusquicktigame2d
2012 03-03-titanium plusquicktigame2d
 
Unity C#3からC#6に向けて
Unity C#3からC#6に向けてUnity C#3からC#6に向けて
Unity C#3からC#6に向けて
 
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスするEWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
EWD 3トレーニングコース#19 JavaScriptからGlobalストレジにアクセスする
 
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクトEWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
EWD 3トレーニングコース#20 GlobalストレージのJavaScript用抽象化-(a)DocumentNodeオブジェクト
 
CodeIgniterによるPhwittr
CodeIgniterによるPhwittrCodeIgniterによるPhwittr
CodeIgniterによるPhwittr
 
TypeScript と Visual Studio Code
TypeScript と Visual Studio CodeTypeScript と Visual Studio Code
TypeScript と Visual Studio Code
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 2.5.0対応)
 
PGCon.jp 2014 jsonb-datatype-20141205
PGCon.jp 2014 jsonb-datatype-20141205PGCon.jp 2014 jsonb-datatype-20141205
PGCon.jp 2014 jsonb-datatype-20141205
 
Creators'night#14今井
Creators'night#14今井Creators'night#14今井
Creators'night#14今井
 
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
NGSIv1 を知っている開発者向けの NGSIv2 の概要 (Orion 3.0.0対応)
 

More from Masahiro Wakame

GoCon2016 spring 自作Webフレームワーク uconを作った話
GoCon2016 spring 自作Webフレームワーク uconを作った話GoCon2016 spring 自作Webフレームワーク uconを作った話
GoCon2016 spring 自作Webフレームワーク uconを作った話Masahiro Wakame
 
ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3Masahiro Wakame
 
TypeScriptは明日から使うべき
TypeScriptは明日から使うべきTypeScriptは明日から使うべき
TypeScriptは明日から使うべきMasahiro Wakame
 
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部Masahiro Wakame
 
Google Glassでできること XE12版 最新開発情報 Mirror API & GDK
Google Glassでできること XE12版 最新開発情報 Mirror API & GDKGoogle Glassでできること XE12版 最新開発情報 Mirror API & GDK
Google Glassでできること XE12版 最新開発情報 Mirror API & GDKMasahiro Wakame
 
コンパイラ指向ReVIEW
コンパイラ指向ReVIEWコンパイラ指向ReVIEW
コンパイラ指向ReVIEWMasahiro Wakame
 
20ヶ月を取り戻す Dart flight school
20ヶ月を取り戻す Dart flight school20ヶ月を取り戻す Dart flight school
20ヶ月を取り戻す Dart flight schoolMasahiro Wakame
 
Google Glassでできること XE11版 最新開発情報 Mirror API & GDK
Google Glassでできること XE11版 最新開発情報 Mirror API & GDKGoogle Glassでできること XE11版 最新開発情報 Mirror API & GDK
Google Glassでできること XE11版 最新開発情報 Mirror API & GDKMasahiro Wakame
 
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例Masahiro Wakame
 
ReVIEW & CI - ChefでCI環境構築
ReVIEW & CI - ChefでCI環境構築ReVIEW & CI - ChefでCI環境構築
ReVIEW & CI - ChefでCI環境構築Masahiro Wakame
 
Firefox OS勉強会 2nd TypeScript+AngularJS
Firefox OS勉強会 2nd TypeScript+AngularJSFirefox OS勉強会 2nd TypeScript+AngularJS
Firefox OS勉強会 2nd TypeScript+AngularJSMasahiro Wakame
 
AngularJS+TypeScript - AngularJS 1周年記念勉強会
AngularJS+TypeScript - AngularJS 1周年記念勉強会AngularJS+TypeScript - AngularJS 1周年記念勉強会
AngularJS+TypeScript - AngularJS 1周年記念勉強会Masahiro Wakame
 
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例までBuildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例までMasahiro Wakame
 
俺とお前とGoogleware
俺とお前とGoogleware俺とお前とGoogleware
俺とお前とGooglewareMasahiro Wakame
 
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作ったDatastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作ったMasahiro Wakame
 

More from Masahiro Wakame (20)

GoCon2016 spring 自作Webフレームワーク uconを作った話
GoCon2016 spring 自作Webフレームワーク uconを作った話GoCon2016 spring 自作Webフレームワーク uconを作った話
GoCon2016 spring 自作Webフレームワーク uconを作った話
 
ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3ng-japan 2015 TypeScript+AngularJS 1.3
ng-japan 2015 TypeScript+AngularJS 1.3
 
TypeScriptは明日から使うべき
TypeScriptは明日から使うべきTypeScriptは明日から使うべき
TypeScriptは明日から使うべき
 
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部
 
Google Glass XE17版
Google Glass XE17版Google Glass XE17版
Google Glass XE17版
 
Google Glassでできること XE12版 最新開発情報 Mirror API & GDK
Google Glassでできること XE12版 最新開発情報 Mirror API & GDKGoogle Glassでできること XE12版 最新開発情報 Mirror API & GDK
Google Glassでできること XE12版 最新開発情報 Mirror API & GDK
 
コンパイラ指向ReVIEW
コンパイラ指向ReVIEWコンパイラ指向ReVIEW
コンパイラ指向ReVIEW
 
20ヶ月を取り戻す Dart flight school
20ヶ月を取り戻す Dart flight school20ヶ月を取り戻す Dart flight school
20ヶ月を取り戻す Dart flight school
 
TypeScript 独習会
TypeScript 独習会TypeScript 独習会
TypeScript 独習会
 
Google Glassでできること XE11版 最新開発情報 Mirror API & GDK
Google Glassでできること XE11版 最新開発情報 Mirror API & GDKGoogle Glassでできること XE11版 最新開発情報 Mirror API & GDK
Google Glassでできること XE11版 最新開発情報 Mirror API & GDK
 
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例
 
ReVIEW & CI - ChefでCI環境構築
ReVIEW & CI - ChefでCI環境構築ReVIEW & CI - ChefでCI環境構築
ReVIEW & CI - ChefでCI環境構築
 
Firefox OS勉強会 2nd TypeScript+AngularJS
Firefox OS勉強会 2nd TypeScript+AngularJSFirefox OS勉強会 2nd TypeScript+AngularJS
Firefox OS勉強会 2nd TypeScript+AngularJS
 
AngularJS+TypeScript - AngularJS 1周年記念勉強会
AngularJS+TypeScript - AngularJS 1周年記念勉強会AngularJS+TypeScript - AngularJS 1周年記念勉強会
AngularJS+TypeScript - AngularJS 1周年記念勉強会
 
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例までBuildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
 
俺とお前とGoogleware
俺とお前とGoogleware俺とお前とGoogleware
俺とお前とGoogleware
 
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作ったDatastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
 
TypeScript 勉強会
TypeScript 勉強会TypeScript 勉強会
TypeScript 勉強会
 
TypeScript Hands-on
TypeScript Hands-onTypeScript Hands-on
TypeScript Hands-on
 
わかめモナ化LT
わかめモナ化LTわかめモナ化LT
わかめモナ化LT
 

Recently uploaded

Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Danieldanielhu54
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxAtomu Hidaka
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムsugiuralab
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdffurutsuka
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directoryosamut
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略Ryo Sasaki
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。iPride Co., Ltd.
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000Shota Ito
 

Recently uploaded (9)

Postman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By DanielPostman LT Fukuoka_Quick Prototype_By Daniel
Postman LT Fukuoka_Quick Prototype_By Daniel
 
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptxIoT in the era of generative AI, Thanks IoT ALGYAN.pptx
IoT in the era of generative AI, Thanks IoT ALGYAN.pptx
 
スマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システムスマートフォンを用いた新生児あやし動作の教示システム
スマートフォンを用いた新生児あやし動作の教示システム
 
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
新人研修のまとめ       2024/04/12の勉強会で発表されたものです。新人研修のまとめ       2024/04/12の勉強会で発表されたものです。
新人研修のまとめ 2024/04/12の勉強会で発表されたものです。
 
UPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdfUPWARD_share_company_information_20240415.pdf
UPWARD_share_company_information_20240415.pdf
 
20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory20240412_HCCJP での Windows Server 2025 Active Directory
20240412_HCCJP での Windows Server 2025 Active Directory
 
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
[DevOpsDays Tokyo 2024] 〜デジタルとアナログのはざまに〜 スマートビルディング爆速開発を支える 自動化テスト戦略
 
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
Amazon SES を勉強してみる その12024/04/12の勉強会で発表されたものです。
 
PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000PHP-Conference-Odawara-2024-04-000000000
PHP-Conference-Odawara-2024-04-000000000
 

GoCon 2015 Summer GoのASTをいじくって新しいツールを作る

  • 2. わかめ まさひろ @vvakame TypeScript Masahiro Wakame DefinitelyTyped appengine photo from golang.org/doc/gopher/
  • 4. encoding/json play.golang.org/p/T9uO25D2xz … 
 type Game struct {
 ID int64 `json:"id"`
 Title string `json:"title"`
 Price int `json:"price"`
 InDevelopment bool `json:"inDevelopment"`
 ShippedAt time.Time `json:"shippedAt"`
 }
 
 func main() {
 game := &Game{
 ID: 1,
 Title: "Splatoon",
 Price: 5700,
 InDevelopment: false,
 }
 b, _ := json.Marshal(game)
 fmt.Println(string(b))
 }
  • 5. encoding/json … 
 type Game struct {
 ID int64 `json:"id"`
 Title string `json:"title"`
 Price int `json:"price"`
 InDevelopment bool `json:"inDevelopment"`
 ShippedAt time.Time `json:"shippedAt"`
 }
 
 func main() {
 game := &Game{
 ID: 1,
 Title: "Splatoon",
 Price: 5700,
 InDevelopment: false,
 }
 b, _ := json.Marshal(game)
 fmt.Println(string(b))
 } 手書き!? 正気か!?!? めんどい “ 閉じるの忘れる typoる
  • 6. jwg 作った //go:generate jwg -output model_json.go .
 package sample
 
 … 
 // +jwg
 type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 }
 
 func main() {
 game := &Game{
 ID: 1, Title: "Splatoon", Price: 5700, InDevelopment: false,
 }
 jsonObj, _ := NewGameJsonBuilder().AddAll().Convert(game)
 b, _ := json.Marshal(jsonObj)
 fmt.Println(string(b))
 } jwg = Json Wrapper Generator
  • 7. //go:generate jwg -output model_json.go .
 package sample
 
 … 
 // +jwg
 type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 }
 
 func main() {
 game := &Game{
 ID: 1, Title: "Splatoon", Price: 5700, InDevelopment: false,
 }
 jsonObj, _ := NewGameJsonBuilder().AddAll().Convert(game)
 b, _ := json.Marshal(jsonObj)
 fmt.Println(string(b))
 } go generate 使う! コメントにタグ書く(標準仕様などない! 生成したコード利用だ! jwg 作った
  • 8. 自動生成! type GameJson struct {
 ID int64 `json:"id,omitempty"`
 Title string `json:"title,omitempty"`
 Price int `json:"price,omitempty"`
 InDevelopment bool `json:"inDevelopment,omitempty"`
 ShippedAt time.Time `json:"shippedAt,omitempty"`
 } 楽
  • 9. その他! type GameJson func (orig *GameJson) Convert() (*Game, error) type GameJsonBuilder func NewGameJsonBuilder() *GameJsonBuilder func (b *GameJsonBuilder) Add(info *GamePropertyInfo) *GameJsonBuilder func (b *GameJsonBuilder) AddAll() *GameJsonBuilder func (b *GameJsonBuilder) Convert(orig *Game) (*GameJson, error) func (b *GameJsonBuilder) ConvertList(orig []*Game) (GameJsonList, error) func (b *GameJsonBuilder) Marshal(orig *Game) ([]byte, error) func (b *GameJsonBuilder) Remove(info *GamePropertyInfo) *GameJsonBuilder type GameJsonList func (jsonList GameJsonList) Convert() ([]*Game, error) type GamePropertyDecoder type GamePropertyEncoder type GamePropertyInfo *JsonBuilder *Property(De|En)coder *PropertyInfo
  • 10. Web API作成用 play.golang.org/p/5wYA62Njvn func (b *GameJsonBuilder) AddSite() *GameJsonBuilder {
 b.AddAll()
 b.Remove(b.ID) // IDは内部情報なのでいらない
 b.Price.Encoder = func(src *Game, dest *GameJson) error {
 if !src.InDevelopment {
 dest.Price = src.Price // 開発中じゃない時だけ価格を出すよ!
 }
 return nil
 }
 
 return b
 }
 
 func main() {
 game := &Game{
 ID: 2, Title: "Secret of Yaba", Price: 9999, InDevelopment: true,
 }
 jsonObj, _ := NewGameJsonBuilder().AddSite().Convert(game)
 b, _ := json.Marshal(jsonObj)
 fmt.Println(string(b))
 } { "title":"Secret of Yaba”, “inDevelopment":true, “shippedAt":"0001-01-01T00:00:00Z" } 実行結果→
  • 13. 主張 • コード生成 is 便利 • GoだとGenericsないしコード増えがち • コンパイル時チェックの恩恵! • 文字列で指定とか時代遅れだよね∼ • 元コード→データ化→加工→生成! • まずはソースコードを解析しないと!
  • 14. 正規表現で頑張る http://play.golang.org/p/fsOl7CcjgB package main
 
 import (
 "fmt"
 "regexp"
 )
 
 func main() {
 code := `
 type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 }
 `
 
 re:=regexp.MustCompile(`s*types+([a-zA-Z]+)s+structs+{n(?:s*([a-zA-Z0-9]+)s+([a-zA-Z0-9.]+)s*n)*s*}`)
 result := re.FindAllStringSubmatch(code,-1)
 fmt.Printf("%#v", result)
 }
  • 16. ASTを活用する • AST = Abstract Syntax Tree • 本来はコンパイラ内部の中間表現 • ソースコードをデータとして使える! • コード解析はライブラリに任せよう! • 解析後のコード組立に専念できる!
  • 19. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl
  • 20. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec type (
 A struct {
 Foo string
 }
 B struct {
 Bar string
 }
 ) こういう記法もある(怖い
  • 21. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec ast.Ident
  • 22. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec ast.Ident ast.StructType
  • 23. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec ast.Ident ast.StructType ast.FieldList
  • 24. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec ast.Ident ast.StructType ast.FieldList ast.Field type A struct {
 Foo, Bar string
 } こういう記法もある(怖い
  • 25. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec ast.Ident ast.StructType ast.FieldList ast.Field ast.Ident
  • 26. Game struct → AST type Game struct {
 ID int64
 Title string
 Price int
 InDevelopment bool
 ShippedAt time.Time
 } ast = go/ast package ast.GenDecl ast.TypeSpec ast.Ident ast.StructType ast.FieldList ast.Field ast.Ident ast.Ident
  • 29. ツール開発の流れ 1. 処理対象(のstruct)を決める 2. コード生成結果を手書きする •名前を機械的に考えてつけよう 3. 必要な俺形式のデータ構造を設計する •ASTから取れるか?不足はないか? •型情報取れなくて辛いパターンある 4. 頑張ってAST取って変換して生成処理書く
  • 30. Goコードの構造 // generated by jwg -output model_json.go .; DO NOT EDIT
 
 package sample
 
 import (
 "encoding/json"
 "time"
 )
 
 // for Game
 type GameJson struct {
 ID int64 `json:"id,omitempty"`
 Title string `json:"title,omitempty"`
 Price int `json:"price,omitempty"`
 InDevelopment bool `json:"inDevelopment,omitempty"`
 ShippedAt time.Time `json:"shippedAt,omitempty"`
 }
 PackageClause ImportDecl TopLevelDecl
  • 31. 俺形式が必要な理由 // generated by jwg -output model_json.go .; DO NOT EDIT
 
 package sample
 
 import (
 "encoding/json"
 "time"
 )
 
 // for Game
 type GameJson struct {
 ID int64 `json:"id,omitempty"`
 Title string `json:"title,omitempty"`
 Price int `json:"price,omitempty"`
 InDevelopment bool `json:"inDevelopment,omitempty"`
 ShippedAt time.Time `json:"shippedAt,omitempty"`
 }
 正しいPackageClauseの生成には、 TopLevelDecl生成結果の把握が必要! etc..
  • 32. 代表的な俺形式 • Source (生成結果ソース全体) • Struct (生成するstruct1個分) • Field (↑のfield1個分) • Tag (↑に付属するtag情報)
  • 33. jwgの場合 // BuildStruct represents source code of assembling..
 type BuildSource struct {
 g *genbase.Generator
 pkg *genbase.PackageInfo
 typeInfos genbase.TypeInfos
 
 Structs []*BuildStruct
 }
 
 // BuildStruct represents struct of assembling..
 type BuildStruct struct {
 parent *BuildSource
 typeInfo *genbase.TypeInfo
 
 Fields []*BuildField
 }
 
 // BuildField represents field of BuildStruct.
 type BuildField struct {
 parent *BuildStruct
 fieldInfo *genbase.FieldInfo
 
 Name string
 Embed bool
 Tag *BuildTag
 }
 
 // BuildTag represents tag of BuildField.
 type BuildTag struct {
 field *BuildField
 
 Name string
 Ignore bool // e.g. Secret string `json:"-"`
 DoNotEmit bool // e.g. Field int `json:",omitempty"`
 String bool // e.g. Int64String int64 `json:",string"`
 }
  • 34. genbaseのご紹介 • 3つほどコード生成ツール作った • 定形処理の存在に気がつく • AST読み込み • 指定されたorタグ付きstructの収集 • import句の管理 • コード組み立て・フォーマット • その他便利関数とか github.com/favclip/genbase 参考:typewriter
  • 35. そして気合 func (st *BuildStruct) emit(g *genbase.Generator) error {
 g.Printf("// for %sn", st.Name())
 
 // generate FooJson struct from Foo struct
 g.Printf("type %sJson struct {n", st.Name())
 for _, field := range st.Fields {
 if field.Tag.Ignore {
 continue
 }
 postfix := ""
 if field.WithJWG() {
 postfix = "Json"
 }
 tagString := field.Tag.TagString()
 if tagString != "" {
 tagString = fmt.Sprintf("`%s`", tagString)
 }
 if field.Embed {
 g.Printf("%s%s %sn", field.fieldInfo.TypeName(), postfix, tagString)
 } else {
 g.Printf("%s %s%s %sn", field.Name, field.fieldInfo.TypeName(), postfix, tagString)
 }
 }
 g.Printf("}nn")
 
 g.Printf("type %[1]sJsonList []*%[1]sJsonnn", st.Name())
 
 // generate property builder
 g.Printf("type %[1]sPropertyEncoder func(src *%[1]s, dest *%[1]sJson) errornn", st.Name())
 g.Printf("type %[1]sPropertyDecoder func(src *%[1]sJson, dest *%[1]s) errornn", st.Name())
 
 // generate property info
 g.Printf(`
 type %[1]sPropertyInfo struct {
 name string
 Encoder %[1]sPropertyEncoder
 Decoder %[1]sPropertyDecoder
 }
 
 `, st.Name())
 
 // generate json builder
 ↓ざっくり500行続く
  • 36. デカさ • genbase • ざっくり580行くらい • jwg • ざっくり850行くらい • 生成後コード読んでから読めば理解る • …んじゃないかな多分
  • 37. Tips • 埋め込みstructは敵 • 生成すべきコードがどんどん複雑に… • fieldの型がstructだと絶望 • ASTだけでは型の詳細な情報がない • 生成コードないとコンパイル通らん • Printfの %[1]s 記法マジ便利
  • 38. I ♥ Pull Request • よりGoらしい書き方できるよ! • より効率の良い実装があるよ! • Template使えよ! • text/template は気に入らなかった… • なんかないですかね? github.com/favclip
  • 40. We are hiring! • 開発:テレビ朝日 • jwg, genbase 他 爆誕! • http://www.favclip.com/ • appengine/go開発者絶賛募集中!
  • 42. 疑問 • ライブラリのリビジョン? • jwg 非互換な変更していいのかしら • embedしたstructのメソッド呼び奴 • 外側のstructがreceiverになってほし • Generics欲しい気持ちが抑えられない
  • 43. 怒り💢 • stringのslice取ると[]byteなのやめて💢 • 1文字=1バイトマンが作るライブラリ • 再帰的なパッケージ参照許して💢 • 1パッケージが際限なくでかくなる… • err != nil 毎回やるのだるい💢