Recommended
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PDF
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PDF
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
PDF
Hello Dark-Side C# (Part. 1)
PDF
An Internal of LINQ to Objects
PPTX
C# 7.2 with .NET Core 2.1
PDF
Reactive Extensionsで非同期処理を簡単に
PDF
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
PDF
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
PPTX
PPT
Scripting Layer for Android + Perl
PDF
PPTX
C# 8.0 Preview in Visual Studio 2019 (16.0)
PPT
PDF
中3女子が狂える本当に気持ちのいい constexpr
PDF
PDF
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
PPTX
PDF
PDF
PDF
PDF
PDF
Async design with Unity3D
PDF
PPTX
PDF
PDF
Cプログラマのためのカッコつけないプログラミングの勧め
PDF
メルカリ・ソウゾウでは どうGoを活用しているのか?
PDF
More Related Content
PDF
Observable Everywhere - Rxの原則とUniRxにみるデータソースの見つけ方
PDF
History & Practices for UniRx UniRxの歴史、或いは開発(中)タイトルの用例と落とし穴の回避法
PDF
CEDEC 2018 最速のC#の書き方 - C#大統一理論へ向けて性能的課題を払拭する
PDF
Hello, C++ + JavaScript World! - Boost.勉強会 #11 東京
PDF
Hello Dark-Side C# (Part. 1)
PDF
An Internal of LINQ to Objects
PPTX
C# 7.2 with .NET Core 2.1
PDF
Reactive Extensionsで非同期処理を簡単に
What's hot
PDF
ZeroFormatter/MagicOnion - Fastest C# Serializer/gRPC based C# RPC
PDF
What, Why, How Create OSS Libraries - 過去に制作した30のライブラリから見るC#コーディングテクニックと個人OSSの...
PPTX
PPT
Scripting Layer for Android + Perl
PDF
PPTX
C# 8.0 Preview in Visual Studio 2019 (16.0)
PPT
PDF
中3女子が狂える本当に気持ちのいい constexpr
PDF
PDF
ZeroFormatterに見るC#で最速のシリアライザを作成する100億の方法
PPTX
PDF
PDF
PDF
PDF
PDF
Async design with Unity3D
PDF
PPTX
PDF
PDF
Cプログラマのためのカッコつけないプログラミングの勧め
Similar to GoCon 2015 Summer GoのASTをいじくって新しいツールを作る
PDF
メルカリ・ソウゾウでは どうGoを活用しているのか?
PDF
PDF
F#+Erlangで簡単なシューティングゲームを作ってみている
KEY
Java One 2012 Tokyo JVM Lang. BOF(Groovy)
PDF
PDF
PDF
PDF
PDF
New feature of Groovy2.0 G*Workshop
PPTX
Androidで使えるJSON-Javaライブラリ
PDF
PPTX
20130228 Goノススメ(BPStudy #66)
KEY
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
PDF
Android App Development with Gradle & Android Studio
PDF
Google Developer Day 2010 Japan: プログラミング言語 Go (鵜飼 文敏)
PDF
Gws 20130315 gradle_handson
More from Masahiro Wakame
PDF
GoCon2016 spring 自作Webフレームワーク uconを作った話
PDF
ng-japan 2015 TypeScript+AngularJS 1.3
PDF
PDF
TypeScript 型定義ファイルのある開発 TypeScript勉強会 VSハッカソン倶楽部
PDF
PDF
Google Glassでできること XE12版 最新開発情報 Mirror API & GDK
PDF
PDF
20ヶ月を取り戻す Dart flight school
PDF
PDF
Google Glassでできること XE11版 最新開発情報 Mirror API & GDK
PDF
CEATEC Glassware(Google Glassアプリ)開発の指南と開発事例
PDF
ReVIEW & CI - ChefでCI環境構築
PDF
Firefox OS勉強会 2nd TypeScript+AngularJS
PDF
AngularJS+TypeScript - AngularJS 1周年記念勉強会
PDF
Buildinsider OFFLINE TypeScriptの基礎から実践・利用事例まで
PDF
PDF
Datastoreへのアクセスを楽してMemcacheアクセスに置き換えるライブラリ作った
PDF
PDF
PDF
GoCon 2015 Summer GoのASTをいじくって新しいツールを作る 1. 2. 3. 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"
}
実行結果→
11. 12. 13. 主張
• コード生成 is 便利
• GoだとGenericsないしコード増えがち
• コンパイル時チェックの恩恵!
• 文字列で指定とか時代遅れだよね∼
• 元コード→データ化→加工→生成!
• まずはソースコードを解析しないと!
14. 15. 16. ASTを活用する
• AST = Abstract Syntax Tree
• 本来はコンパイラ内部の中間表現
• ソースコードをデータとして使える!
• コード解析はライブラリに任せよう!
• 解析後のコード組立に専念できる!
17. 18. 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
27. 28. 29. 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. 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. 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. 37. 38. I ♥ Pull Request
• よりGoらしい書き方できるよ!
• より効率の良い実装があるよ!
• Template使えよ!
• text/template は気に入らなかった…
• なんかないですかね?
github.com/favclip
39. 40. We are hiring!
• 開発:テレビ朝日
• jwg, genbase 他 爆誕!
• http://www.favclip.com/
• appengine/go開発者絶賛募集中!
41. 42. 43.