go-startA high level web-framework for Go
Goals• Create a high level web-framework for Go,  like Django for Python or Rails for Ruby• Be Go-ish• Don’t make stuff mo...
Current status• In development for 10 months• Work sponsored by STARTeurope• Used in production for http://startuplive.in•...
What’s in it?• MVC• Prefer Go syntax to template languages• HTML5 Boilerplate out of the box• MongoDB• All batteries inclu...
All batteries included• HTML5 Boilerplate• jQuery• External dependencies fetched  automatically:  go get -u github.com/ung...
Views
Philosophy• Why learn another template language if you  can use Go syntax?• DOM tree has a 1:1 Go object  representation o...
Higher level abstractions• view.List      • view.Menu• view.Table     • view.Video• view.Form      • view.Page• view.Model...
HTML Tags / Shortcuts• H1, H2, ...   • Br•P              • B, I, Q• Pre           • Em, Strong• A, A_blank    • Ul, Ol• Img
So how does a view look         like?
view := Views{! NewDiv("myclass",! ! H1("Example HTML structure"),! ! P("This is a paragraph"),! ! P(! ! ! HTML("Some unes...
Yes, templates are    supported
But I ended up using them   only for the HTML5Boilerplate Page template
Dynamic Views
view := NewDynamicView(!   func(context *Context) (view View, err error) {!   !    var names []string!   !    i := models....
view := &ModelView{!   GetModelIterator: func(context *Context) model.Iterator {!   !    return models.Users.Sort("Name.Fi...
HTML Pages
Homepage := &Page{!   OnPreRender: func(page *Page, context *Context) (err error) {!   !    context.Data = &PerPageData{.....
URL structure
Admin_Auth := NewBasicAuth("go-start.org", "admin", "password123")func Paths() *ViewPath {!   return &ViewPath{View: Homep...
Running the server
view.Init("go-start.org", CookieSecret, "pkg/myproject", "pkg/gostart")view.Config.RedirectSubdomains = []string{"www"}vie...
Models
Models• Models are Go structs  (marshaling via reflection)• Meta information for validation and display  is added via tags•...
FormModel
type SignupFormModel struct {!   Email     model.Email     `gostart:"required"`!   Password1 model.Password `gostart:"requ...
mongo.Document
type ExampleDoc struct {!   mongo.DocumentBase `bson:",inline"`                  // Give it a Mongo ID!   Person          ...
mongo.Collection
var ExampleDocs *mongo.Collection = mongo.NewCollection("exampledocs", (*ExampleDoc)(nil))
mongo.Query
i := models.Users.Filter("Name.Last", "Smith").Sort("Name.First").Iterator();for doc := i.Next(); doc != nil; doc = i.Next...
Create, modify, save a mongo.Document
user := models.Users.NewDocument().(*models.User)user.Name.First.Set("Erik")user.Name.Last.Set("Unger")doc, err := models....
Additional packages• Email (message creation missing in standard  mail package + Google Mail defaults)• Gravatar• RSS pars...
Where to get it• go get -u github.com/ungerik/go-start• Documentation: http://go-start.org/
One more thing ;-)
We are hiring!    STARTeurope
Go+Javascript Pioneers         (Vienna)
The End          Questions?• erik.unger@starteurope.at• Twitter: @ungerik• Skype: ungerik
The go-start webframework (GTUG Vienna 27.03.2012)
The go-start webframework (GTUG Vienna 27.03.2012)
Upcoming SlideShare
Loading in …5
×

The go-start webframework (GTUG Vienna 27.03.2012)

1,693 views
1,656 views

Published on

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
1,693
On SlideShare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
20
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • \n
  • The go-start webframework (GTUG Vienna 27.03.2012)

    1. 1. go-startA high level web-framework for Go
    2. 2. Goals• Create a high level web-framework for Go, like Django for Python or Rails for Ruby• Be Go-ish• Don’t make stuff more complicated than it has to be• Convention over configuration• Easy setup and deployment
    3. 3. Current status• In development for 10 months• Work sponsored by STARTeurope• Used in production for http://startuplive.in• Go v1.0
    4. 4. What’s in it?• MVC• Prefer Go syntax to template languages• HTML5 Boilerplate out of the box• MongoDB• All batteries included
    5. 5. All batteries included• HTML5 Boilerplate• jQuery• External dependencies fetched automatically: go get -u github.com/ungerik/go-start
    6. 6. Views
    7. 7. Philosophy• Why learn another template language if you can use Go syntax?• DOM tree has a 1:1 Go object representation on the server• Every element has an ID to enable sync of DOM tree and server view representation
    8. 8. Higher level abstractions• view.List • view.Menu• view.Table • view.Video• view.Form • view.Page• view.ModelView• view.If
    9. 9. HTML Tags / Shortcuts• H1, H2, ... • Br•P • B, I, Q• Pre • Em, Strong• A, A_blank • Ul, Ol• Img
    10. 10. So how does a view look like?
    11. 11. view := Views{! NewDiv("myclass",! ! H1("Example HTML structure"),! ! P("This is a paragraph"),! ! P(! ! ! HTML("Some unescaped HTML:<br/>"),! ! ! Printf("The number of the beast: %d", 666),! ! ! Escape("Will be escaped: 666 < 999"),! ! ),! ! A_blank("http://go-lang.org", "A very simple link"),! ),! Hr(),! Pre("! <- pre formated text, followed by a list:"),! Ul("red", "green", "blue"),! &Template{! ! Filename: "mytemplate.html",! ! GetContext: func(ctx *Context) (interface{}, error) {! ! ! return map[string]string{"Key": "Value"}, nil! ! },! },}
    12. 12. Yes, templates are supported
    13. 13. But I ended up using them only for the HTML5Boilerplate Page template
    14. 14. Dynamic Views
    15. 15. view := NewDynamicView(! func(context *Context) (view View, err error) {! ! var names []string! ! i := models.Users.Sort("Name.First").Sort("Name.Last").Iterator();! ! for doc := i.Next(); doc != nil; doc = i.Next() {! ! ! names = append(names, doc.(*models.User).Name.String())! ! }! ! if i.Err() != nil {! ! ! return nil, i.Err()! ! }! ! !! ! return &List{! // List = higher level abstraction, Ul() = shortcut! ! ! Class: "my-ol",! ! ! Ordered: true,! ! ! Model: EscapeStringsListModel(names),! ! }, nil! },)
    16. 16. view := &ModelView{! GetModelIterator: func(context *Context) model.Iterator {! ! return models.Users.Sort("Name.First").Sort("Name.Last").Iterator()! },! GetModelView: func(model interface{}, context *Context) (view View, err error) {! ! user := model.(*models.User)! ! return PrintfEscape("%s, ", user.Name), nil! },}
    17. 17. HTML Pages
    18. 18. Homepage := &Page{! OnPreRender: func(page *Page, context *Context) (err error) {! ! context.Data = &PerPageData{...} // Set global page data at request context! },! WriteTitle: func(context *Context, writer io.Writer) (err error) {! ! writer.Write([]byte(context.Data.(*PerPageData).DynamicTitle))! ! return nil! },! CSS: HomepageCSS,! WriteHeader: RSS("go-start.org RSS Feed", &RssFeed)! WriteScripts: PageWriters(! ! Config.Page.DefaultWriteScripts,! ! JQuery, // jQuery/UI is built-in! ! JQueryUI,! ! JQueryUIAutocompleteFromURL(".select-username", IndirectURL(&API_Usernames), 2),! ! GoogleAnalytics(GoogleAnalyticsID), // Google Analytics is built-in! )! Content: Views{},}
    19. 19. URL structure
    20. 20. Admin_Auth := NewBasicAuth("go-start.org", "admin", "password123")func Paths() *ViewPath {! return &ViewPath{View: Homepage, Sub: []ViewPath{ // /! ! {Name: "style.css", View: HomepageCSS}, // /style.css! ! {Name: "feed", View: RssFeed}, // /feed/! ! {Name: "admin", View: Admin, Auth: Admin_Auth, Sub: []ViewPath{ // /admin/! ! ! {Name: "user", Args: 1, View: Admin_User, Auth: Admin_Auth},// /admin/user/<ID>/! ! }},! ! {Name: "api", Sub: []ViewPath{ // 404 because no view defined! ! ! {Name: "users.json", View: API_Usernames}, // /api/users.json! ! }},! }}
    21. 21. Running the server
    22. 22. view.Init("go-start.org", CookieSecret, "pkg/myproject", "pkg/gostart")view.Config.RedirectSubdomains = []string{"www"}view.Config.Page.DefaultMetaViewport = "width=960px"view.RunConfigFile(Paths(), "run.config")
    23. 23. Models
    24. 24. Models• Models are Go structs (marshaling via reflection)• Meta information for validation and display is added via tags• Forms and DB share the same model and validation mechanism• MongoDB is the default database
    25. 25. FormModel
    26. 26. type SignupFormModel struct {! Email model.Email `gostart:"required"`! Password1 model.Password `gostart:"required|label=Password|minlen=6"`! Password2 model.Password `gostart:"label=Repeat password"`}func (self *SignupFormModel) Validate(metaData model.MetaData) []*model.ValidationError {! if self.Password1 != self.Password2 {! ! return model.NewValidationErrors(os.NewError("Passwords dont match"), metaData)! }! return model.NoValidationErrors}form := &Form{! ButtonText: "Signup",! FormID: "user_signup",! GetModel: func(form *Form, context *Context) (interface{}, error) {! ! return &SignupFormModel{}, nil! },! OnSubmit: func(form *Form, formModel interface{}, context *Context) (err error) {! ! m := formModel.(*SignupFormModel)! ! // ... create user in db and send confirmation email ...! ! return err! },}
    27. 27. mongo.Document
    28. 28. type ExampleDoc struct {! mongo.DocumentBase `bson:",inline"` // Give it a Mongo ID! Person mongo.Ref `gostart:"to=people"` // Mongo ID ref to a document in"people" collection! LongerText model.Text `gostart:"rows=5|cols=80|maxlen=400"`! Integer model.Int `gostart:"min=1|max=100"`! Email model.Email // Normalization + special treament in forms! PhoneNumber model.Phone // Normalization + special treament in forms! Password model.Password // Hashed + special treament in forms! SubDoc struct {! ! Day model.Date! ! RealFloat model.Float `gostart:"valid"! ! Drinks []mongo.Choice `gostart:"options=Beer,Wine,Water"`! }}
    29. 29. mongo.Collection
    30. 30. var ExampleDocs *mongo.Collection = mongo.NewCollection("exampledocs", (*ExampleDoc)(nil))
    31. 31. mongo.Query
    32. 32. i := models.Users.Filter("Name.Last", "Smith").Sort("Name.First").Iterator();for doc := i.Next(); doc != nil; doc = i.Next() {! user := doc.(*models.User)! // ...}// Err() returns any error after Next() returned nil:if i.Err() != nil {! panic(i.Err())}
    33. 33. Create, modify, save a mongo.Document
    34. 34. user := models.Users.NewDocument().(*models.User)user.Name.First.Set("Erik")user.Name.Last.Set("Unger")doc, err := models.Groups.Filter(“Name”, “testgroup”).One()group := doc.(*models.Group)user.Group.Set(group) // sets a mongo.Ref to the group!err := user.Save()
    35. 35. Additional packages• Email (message creation missing in standard mail package + Google Mail defaults)• Gravatar• RSS parsing• Amiando event management (used by http://startuplive.in)
    36. 36. Where to get it• go get -u github.com/ungerik/go-start• Documentation: http://go-start.org/
    37. 37. One more thing ;-)
    38. 38. We are hiring! STARTeurope
    39. 39. Go+Javascript Pioneers (Vienna)
    40. 40. The End Questions?• erik.unger@starteurope.at• Twitter: @ungerik• Skype: ungerik

    ×