A high level web-framework for Go

Overview

go-start is a high level web-framework for Go, like Django for Python or Rails for Ruby.

Installation: go get github.com/ungerik/go-start

Documentation: http://godoc.org/github.com/ungerik/go-start

Tutorial with user login and administration: https://github.com/ungerik/go-start/tree/master/examples/FullTutorial

Presentation Slides: http://speakerdeck.com/u/ungerik/

First real world application: http://startuplive.in/

Copyright (c) 2012 Erik Unger MIT License See: LICENSE file

Intro:

Features:

The case for Go:

https://gist.github.com/3731476

Views:

The philosophy for creating HTML views is (unlike Rails/Django) that you should not have to learn yet another language to be able to write templates. There are several very simple template languages out there that reduce program code like logic within the template, but it’s still yet another syntax to learn.

In go-start the HTML structure of a page is represented by a structure of type safe Go objects. It should feel like writing HTML but using the syntax of Go. And no, it has nothing to do with the mess of intertwined markup and code in PHP.

Example of a static view:

view := Views{
	DIV("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(requestContext *Context) (interface{}, error) {
			return map[string]string{"Key": "Value"}, nil
		},
	},
}

Example of a dynamic view:

view := DynamicView(
	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
	},
)

Beside DynamicView there is also a ModelView. It takes a model.Iterator and creates a dynamic view for every iterated data item:

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
	},
}

Pages and URLs:

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{},
}


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/<USER_ID>/
		}},
		{Name: "api", Sub: []ViewPath{                                      // 404 because no view defined
			{Name: "users.json", View: API_Usernames},                  // /api/users.json
		}},
	}
}

view.Init("go-start.org", CookieSecret, "pkg/myproject", "pkg/gostart") // Set site name, cookie secret and static paths
view.Config.RedirectSubdomains = []string{"www"}     // Redirect from www.
view.Config.Page.DefaultMetaViewport = "width=960px" // Page width for mobile devices
view.RunConfigFile(Paths(), "run.config")            // Run server with path structure and values from config file

Models:

Data is abstacted as models. The same model abstraction and data validation is used for HTML forms and for databases. So a model can be loaded from a database, displayed as an HTML form and saved back to the database after submit. This is not always a good practice, but it shows how easy things can be.

A model is a simple Go struct that uses gostart/model types as struct members. Custom model wide validation is done by adding a Validate() method to the struct type:

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
}

Here is how a HTML form is created that displays input fields for the SignupFormModel:

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
	},
}

MongoDB is the default database of go-start utilizing Gustavo Niemeyer's great lib mgo (http://labix.org/mgo).

Mongo collections and queries are encapsulated to make them compatible with the go-start data model concept, and a little bit easier to use.

Example of a collection and document struct:

var ExampleDocs *mongo.Collection = mongo.NewCollection("exampledocs", (*ExampleDoc)(nil))

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
		Drinks    []mongo.Choice `gostart:"options=Beer,Wine,Water"` // Mongo array of strings
		RealFloat model.Float    `gostart:"valid" // Must be a real float value, not NaN or Inf
	}
}

Example 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())
}

A new mongo.Document is always created by the corresponding collection object to initialize it with meta information about its collection. This way it is possible to implement Save() or Remove() methods for the document.

Example for creating, modifying and saving a document:

user := models.Users.NewDocument().(*models.User)

user.Name.First.Set("Erik")
user.Name.Last.Set("Unger")

err := user.Save()
Issues
  • Do you implement any validation framework?

    Do you implement any validation framework?

    I found this:

    type User struct {
      user.User `bson:",inline"`
      Image  media.ImageRef
      Gender model.Choice `model:"options=,Male,Female"`
    }
    

    Does bson support validatiion?I can't googling any material out about it.And do you implement golang validation like

    jsr303 http://java.dzone.com/articles/bean-validation-and-jsr-303,
    

    Has this model:"options=,Male,Female" any syntax meaning or just "string description"?

    opened by AlexLuya 1
  • Need a way to fill DynamicChoice variables when loading an object from Mongo

    Need a way to fill DynamicChoice variables when loading an object from Mongo

    Structs that have a DynamicChoice variable will not fill when loading from Mongo. I don't know if it has similar functionality with Choice variables.

    Can Go-Start have some kind of functionality where if the struct's DynamicChoice variable is pre-filled with options before querying the database, it will match the index to the correct string when loading from Mongo?

    opened by Mardok 2
Owner
Erik Unger
CTO & Co-Founder DOMONDA GmbH, Software & Aerospace Enthusiast
Erik Unger
Golanger Web Framework is a lightweight framework for writing web applications in Go.

/* Copyright 2013 Golanger.com. All rights reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except

golanger 299 Mar 3, 2022
Goal is a toolkit for high productivity web development in Go language in the spirit of Revel Framework that is built around the concept of code generation.

Goal Goal is a set of tools for high productivity web development in Go language. Goal, being mostly inspired by Revel Framework and its discussions,

null 88 Sep 27, 2021
:bullettrain_side: High-performance web server for Go.

Aero is a high-performance web server with a clean API. Installation go get -u github.com/aerogo/aero/... Usage Run this in an empty directory: aero -

Aero 482 Aug 6, 2022
An ideally refined web framework for Go.

Air An ideally refined web framework for Go. High-performance? Fastest? Almost all web frameworks are using these words to tell people that they are t

Aofei Sheng 417 Jul 3, 2022
Web framework for creating apps using Go in Google AppEngine

Welcome to app.go v3.0 app.go is a simple web framework for use in Google AppEngine. Just copy the app folder to your working folder and import it fro

George Nava 46 Mar 21, 2021
Eudore is the core of a golang lightweight web framework.

Eudore eudore是一个golang轻量级web框架核心,可以轻松扩展成一个技术栈专用框架,具有完整框架设计体系。 反馈和交流请加群组:QQ群373278915。 Features 易扩展:主要设计目标、核心全部解耦,接口即为逻辑。 简单:对象语义明确,框架代码量少复杂度低,无依赖库。 易用

null 72 Jul 30, 2022
Gin is a HTTP web framework written in Go (Golang). It features a Martini-like API with much better performance -- up to 40 times faster. If you need smashing performance, get yourself some Gin.

Gin Web Framework Gin is a web framework written in Go (Golang). It features a martini-like API with performance that is up to 40 times faster thanks

Gin-Gonic 61.7k Aug 8, 2022
a golang web mvc framework, like asp.net mvc.

goku goku is a Web Mvc Framework for golang, mostly like ASP.NET MVC. doc & api Installation To install goku, simply run go get github.com/QLeelulu/go

QLeelulu 275 May 24, 2022
A lightweight RESTful web framework for Go

Goweb A lightweight RESTful web framework for Go. For examples and usage, please read the Goweb API Documentation Read our Articles Who uses Goweb? "U

Stretchr, Inc. 630 May 10, 2022
Fast and Reliable Golang Web Framework

Gramework The Good Framework Gramework long-term testing stand metrics screenshot made with Gramework Stats Dashboard and metrics middleware What is i

null 367 Jul 13, 2022
Mango is a modular web-application framework for Go, inspired by Rack, and PEP333.

Mango Mango is a modular web-application framework for Go, inspired by Rack and PEP333. Note: Not actively maintained. Overview Mango is most of all a

Paul Bellamy 367 Jul 11, 2022
Classy web framework for Go

Martini NOTE: The martini framework is no longer maintained. Martini is a powerful package for quickly writing modular web applications/services in Go

Martini 11.5k Jul 31, 2022
A Go framework for building JSON web services inspired by Dropwizard

Tiger Tonic A Go framework for building JSON web services inspired by Dropwizard. If HTML is your game, this will hurt a little. Like the Go language

Richard Crowley 1k Jul 25, 2022
The web framework for Golang

uAdmin the Golang Web Framework Easy to use, blazing fast and secure. Originally open source by IntegrityNet Solutions and Services For Documentation:

uADMIN 194 Aug 6, 2022
Simple web framework for go, still quite beta at this point

WFDR Framework - Beta Release New 18/Feb/2012: Updated for go 1.0, new directory layout to take advantage of the go build tool. Background There's a m

null 23 Feb 11, 2021
A high performance HTTP request router that scales well

HttpRouter HttpRouter is a lightweight high performance HTTP request router (also called multiplexer or just mux for short) for Go. In contrast to the

Julien Schmidt 14.3k Aug 3, 2022
A simple blog framework built with GO. Uses HTML files and a JSON dict to give you more control over your content.

Go-Blog A simple template based blog framework. Instructions Built for GO version: 1 See the Documentation or Getting Started pages in the wiki. Notes

Matt West 44 Jul 15, 2022
Goldorak GO is a mini framework for the Go programming language. (unfinished dead code)

Goldorak Go =========== > Goldorak GO ! Rétrolaser en action > Goldorak GO !! Va accomplir ta mission > Dans l'infini > Des galaxies > Poursuis ta lu

Bruno Michel 10 Apr 29, 2021
A small and evil REST framework for Go

go-rest A small and evil REST framework for Go Reflection, Go structs, and JSON marshalling FTW! go get github.com/ungerik/go-rest import "github.com/

Erik Unger 125 Apr 18, 2022