SlideShare une entreprise Scribd logo
1  sur  42
go-start
A 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 more complicated than it
  has to be
• Convention over configuration
• Easy setup and deployment
Current status

• In development for 10 months
• Work sponsored by STARTeurope
• Used in production for http://startuplive.in
• Go v1.0
What’s in it?

• MVC
• Prefer Go syntax to template languages
• HTML5 Boilerplate out of the box
• MongoDB
• All batteries included
All batteries included

• HTML5 Boilerplate
• jQuery
• External dependencies fetched
  automatically:
  go get -u github.com/ungerik/go-start
Views
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
Higher level abstractions
• view.List      • view.Menu
• view.Table     • view.Video
• view.Form      • view.Page
• view.ModelView
• view.If
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 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
! ! },
! },
}
Yes, templates are
    supported
But I ended up using them
   only for the HTML5
Boilerplate Page template
Dynamic Views
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
!   },
)
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
!   },
}
HTML Pages
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{},
}
URL structure
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
!   !    }},
!   }
}
Running the server
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")
Models
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
FormModel
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 don't 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
!   },
}
mongo.Document
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"`
!   }
}
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() {
!   user := doc.(*models.User)
!   // ...
}

// Err() returns any error after Next() returned nil:
if i.Err() != nil {
!   panic(i.Err())
}
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.Groups.Filter(“Name”, “testgroup”).One()
group := doc.(*models.Group)
user.Group.Set(group) // sets a mongo.Ref to the group
!
err := user.Save()
Additional packages
• Email (message creation missing in standard
  mail package + Google Mail defaults)
• Gravatar
• RSS parsing
• Amiando event management
  (used by http://startuplive.in)
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

Contenu connexe

Tendances

JavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeJavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your code
Laurence Svekis ✔
 
Dependency Management with RequireJS
Dependency Management with RequireJSDependency Management with RequireJS
Dependency Management with RequireJS
Aaronius
 

Tendances (20)

A Short Introduction To jQuery
A Short Introduction To jQueryA Short Introduction To jQuery
A Short Introduction To jQuery
 
jQuery for beginners
jQuery for beginnersjQuery for beginners
jQuery for beginners
 
JavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your codeJavaScript Advanced - Useful methods to power up your code
JavaScript Advanced - Useful methods to power up your code
 
Django Admin: Widgetry & Witchery
Django Admin: Widgetry & WitcheryDjango Admin: Widgetry & Witchery
Django Admin: Widgetry & Witchery
 
Interacting with the DOM (JavaScript)
Interacting with the DOM (JavaScript)Interacting with the DOM (JavaScript)
Interacting with the DOM (JavaScript)
 
jQuery Features to Avoid
jQuery Features to AvoidjQuery Features to Avoid
jQuery Features to Avoid
 
jQuery Presentation
jQuery PresentationjQuery Presentation
jQuery Presentation
 
Getting Started with DOM
Getting Started with DOMGetting Started with DOM
Getting Started with DOM
 
Feed Normalization with Ember Data 1.0
Feed Normalization with Ember Data 1.0Feed Normalization with Ember Data 1.0
Feed Normalization with Ember Data 1.0
 
Nagios Conference 2014 - Troy Lea - JavaScript and jQuery - Nagios XI Tips, T...
Nagios Conference 2014 - Troy Lea - JavaScript and jQuery - Nagios XI Tips, T...Nagios Conference 2014 - Troy Lea - JavaScript and jQuery - Nagios XI Tips, T...
Nagios Conference 2014 - Troy Lea - JavaScript and jQuery - Nagios XI Tips, T...
 
Javascript: Ajax & DOM Manipulation v1.2
Javascript: Ajax & DOM Manipulation v1.2Javascript: Ajax & DOM Manipulation v1.2
Javascript: Ajax & DOM Manipulation v1.2
 
Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64Alfresco tech talk live public api episode 64
Alfresco tech talk live public api episode 64
 
Jquery ui
Jquery uiJquery ui
Jquery ui
 
Error found
Error foundError found
Error found
 
Selenium再入門
Selenium再入門Selenium再入門
Selenium再入門
 
GDI Seattle - Intro to JavaScript Class 4
GDI Seattle - Intro to JavaScript Class 4GDI Seattle - Intro to JavaScript Class 4
GDI Seattle - Intro to JavaScript Class 4
 
Joomla! Template for Beginners
Joomla! Template for BeginnersJoomla! Template for Beginners
Joomla! Template for Beginners
 
날로 먹는 Django admin 활용
날로 먹는 Django admin 활용날로 먹는 Django admin 활용
날로 먹는 Django admin 활용
 
Dependency Management with RequireJS
Dependency Management with RequireJSDependency Management with RequireJS
Dependency Management with RequireJS
 
Jquery Complete Presentation along with Javascript Basics
Jquery Complete Presentation along with Javascript BasicsJquery Complete Presentation along with Javascript Basics
Jquery Complete Presentation along with Javascript Basics
 

Similaire à The go-start webframework (GTUG Vienna 27.03.2012)

GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
Yared Ayalew
 
Week 4 - jQuery + Ajax
Week 4 - jQuery + AjaxWeek 4 - jQuery + Ajax
Week 4 - jQuery + Ajax
baygross
 

Similaire à The go-start webframework (GTUG Vienna 27.03.2012) (20)

Building a real life application in node js
Building a real life application in node jsBuilding a real life application in node js
Building a real life application in node js
 
GDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App EngineGDG Addis - An Introduction to Django and App Engine
GDG Addis - An Introduction to Django and App Engine
 
Introduction to AngularJS
Introduction to AngularJSIntroduction to AngularJS
Introduction to AngularJS
 
Jquery fundamentals
Jquery fundamentalsJquery fundamentals
Jquery fundamentals
 
Week 4 - jQuery + Ajax
Week 4 - jQuery + AjaxWeek 4 - jQuery + Ajax
Week 4 - jQuery + Ajax
 
Replacing Oracle with MongoDB for a templating application at the Bavarian go...
Replacing Oracle with MongoDB for a templating application at the Bavarian go...Replacing Oracle with MongoDB for a templating application at the Bavarian go...
Replacing Oracle with MongoDB for a templating application at the Bavarian go...
 
MongoDB Munich 2012: MongoDB for official documents in Bavaria
MongoDB Munich 2012: MongoDB for official documents in BavariaMongoDB Munich 2012: MongoDB for official documents in Bavaria
MongoDB Munich 2012: MongoDB for official documents in Bavaria
 
Scalable web application architecture
Scalable web application architectureScalable web application architecture
Scalable web application architecture
 
Introduction to Django
Introduction to DjangoIntroduction to Django
Introduction to Django
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4Python Code Camp for Professionals 3/4
Python Code Camp for Professionals 3/4
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
The Django Web Application Framework 2
The Django Web Application Framework 2The Django Web Application Framework 2
The Django Web Application Framework 2
 
Azure F#unctions
Azure F#unctionsAzure F#unctions
Azure F#unctions
 
FrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridas
FrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridasFrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridas
FrontInBahia 2014: 10 dicas de desempenho para apps mobile híbridas
 
The Django Web Application Framework
The Django Web Application FrameworkThe Django Web Application Framework
The Django Web Application Framework
 
Summit2014 topic 0066 - 10 enhancements that require 10 lines of code
Summit2014 topic 0066 - 10 enhancements that require 10 lines of codeSummit2014 topic 0066 - 10 enhancements that require 10 lines of code
Summit2014 topic 0066 - 10 enhancements that require 10 lines of code
 
Django Girls Mbale [victor's sessions]
Django Girls Mbale [victor's sessions]Django Girls Mbale [victor's sessions]
Django Girls Mbale [victor's sessions]
 
Practical HTML5: Using It Today
Practical HTML5: Using It TodayPractical HTML5: Using It Today
Practical HTML5: Using It Today
 

Dernier

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Safe Software
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
?#DUbAI#??##{{(☎️+971_581248768%)**%*]'#abortion pills for sale in dubai@
 

Dernier (20)

"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
Strategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a FresherStrategies for Landing an Oracle DBA Job as a Fresher
Strategies for Landing an Oracle DBA Job as a Fresher
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
presentation ICT roal in 21st century education
presentation ICT roal in 21st century educationpresentation ICT roal in 21st century education
presentation ICT roal in 21st century education
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
MS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectorsMS Copilot expands with MS Graph connectors
MS Copilot expands with MS Graph connectors
 
Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024Manulife - Insurer Transformation Award 2024
Manulife - Insurer Transformation Award 2024
 
ICT role in 21st century education and its challenges
ICT role in 21st century education and its challengesICT role in 21st century education and its challenges
ICT role in 21st century education and its challenges
 
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers:  A Deep Dive into Serverless Spatial Data and FMECloud Frontiers:  A Deep Dive into Serverless Spatial Data and FME
Cloud Frontiers: A Deep Dive into Serverless Spatial Data and FME
 
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost SavingRepurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
Repurposing LNG terminals for Hydrogen Ammonia: Feasibility and Cost Saving
 
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
+971581248768>> SAFE AND ORIGINAL ABORTION PILLS FOR SALE IN DUBAI AND ABUDHA...
 
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWEREMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
EMPOWERMENT TECHNOLOGY GRADE 11 QUARTER 2 REVIEWER
 
AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024AXA XL - Insurer Innovation Award Americas 2024
AXA XL - Insurer Innovation Award Americas 2024
 

The go-start webframework (GTUG Vienna 27.03.2012)

  • 1. go-start A high level web-framework for Go
  • 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. Current status • In development for 10 months • Work sponsored by STARTeurope • Used in production for http://startuplive.in • Go v1.0
  • 4. What’s in it? • MVC • Prefer Go syntax to template languages • HTML5 Boilerplate out of the box • MongoDB • All batteries included
  • 5. All batteries included • HTML5 Boilerplate • jQuery • External dependencies fetched automatically: go get -u github.com/ungerik/go-start
  • 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. Higher level abstractions • view.List • view.Menu • view.Table • view.Video • view.Form • view.Page • view.ModelView • view.If
  • 9. HTML Tags / Shortcuts • H1, H2, ... • Br •P • B, I, Q • Pre • Em, Strong • A, A_blank • Ul, Ol • Img
  • 10. So how does a view look like?
  • 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. Yes, templates are supported
  • 13. But I ended up using them only for the HTML5 Boilerplate Page template
  • 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. 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 ! }, }
  • 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{}, }
  • 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 ! ! }}, ! } }
  • 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")
  • 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
  • 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 don't 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 ! }, }
  • 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"` ! } }
  • 30. var ExampleDocs *mongo.Collection = mongo.NewCollection("exampledocs", (*ExampleDoc)(nil))
  • 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. Create, modify, save a mongo.Document
  • 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. 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. Where to get it • go get -u github.com/ungerik/go-start • Documentation: http://go-start.org/
  • 38.
  • 39.
  • 40. We are hiring! STARTeurope
  • 42. The End Questions? • erik.unger@starteurope.at • Twitter: @ungerik • Skype: ungerik

Notes de l'éditeur

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n