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()
You might also like...
Gearbox :gear: is a web framework written in Go with a focus on high performance
Gearbox :gear: is a web framework written in Go with a focus on high performance

gearbox ⚙️ is a web framework for building micro services written in Go with a focus on high performance. It's built on fasthttp which is up to 10x fa

High performance, simple Go web framework

Elton Elton的实现参考了koa以及echo,中间件的调整均为洋葱模型:请求由外至内,响应由内至外。主要特性如下: 处理函数(中间件)均以返回error的形式响应出错,方便使用统一的出错处理中间件将出错统一转换为对应的输出(JSON),并根据出错的类型等生成各类统计分析 成功响应数据直接赋值

beego is an open-source, high-performance web framework for the Go programming language.
beego is an open-source, high-performance web framework for the Go programming language.

Beego Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend services. It is inspired by To

letgo is an open-source, high-performance web framework for the Go programming language.

high-performance Lightweight web framework for the Go programming language. golang web framework,高可用golang web框架,go语言 web框架 ,go web

Dragon 🐲 🐲 🐲 is an enterprise high performance web framework with Go for the feature and comfortable develop.

Dragon start dragon ab performance Dragon 🐲 🐲 🐲 is a lightweight high performance web framework with Go for the feature and comfortable develop. 中文

Dragon 🐲 🐲 🐲 is a lightweight high performance web framework with Go for the feature and comfortable develop.

Dragon project new link start dragon ab performance Dragon 🐲 🐲 🐲 is a lightweight high performance web framework with Go for the feature and comfor

⚡ Rux is an simple and fast web framework. support middleware, compatible http.Handler interface. 简单且快速的 Go web 框架,支持中间件,兼容 http.Handler 接口

Rux Simple and fast web framework for build golang HTTP applications. NOTICE: v1.3.x is not fully compatible with v1.2.x version Fast route match, sup

Roche is a Code Generator and Web Framework, makes web development super concise with Go, CleanArch
Roche is a Code Generator and Web Framework, makes web development super concise with Go, CleanArch

It is still under development, so please do not use it. We plan to release v.1.0.0 in the summer. roche is a web framework optimized for microservice

A powerful go web framework for highly scalable and resource efficient web application

webfr A powerful go web framework for highly scalable and resource efficient web application Installation: go get -u github.com/krishpranav/webfr Exa

Comments
  • 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
Flamingo Framework and Core Library. Flamingo is a go based framework for pluggable web projects. It is used to build scalable and maintainable (web)applications.

Flamingo Framework Flamingo is a web framework based on Go. It is designed to build pluggable and maintainable web projects. It is production ready, f

Flamingo 327 Nov 13, 2022
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 298 Nov 14, 2022
The jin is a simplified version of the gin web framework that can help you quickly understand the core principles of a web framework.

jin About The jin is a simplified version of the gin web framework that can help you quickly understand the core principles of a web framework. If thi

null 8 Jul 14, 2022
beego is an open-source, high-performance web framework for the Go programming language.

Beego Beego is used for rapid development of enterprise application in Go, including RESTful APIs, web apps and backend services. It is inspired by To

astaxie 568 Nov 18, 2022
High performance, minimalist Go web framework

Supported Go versions As of version 4.0.0, Echo is available as a Go module. Therefore a Go version capable of understanding /vN suffixed imports is r

LabStack LLC 24.2k Nov 20, 2022
Gearbox :gear: is a web framework written in Go with a focus on high performance

gearbox ⚙️ is a web framework for building micro services written in Go with a focus on high performance. It's built on fasthttp which is up to 10x fa

Gearbox 687 Nov 12, 2022
hiboot is a high performance web and cli application framework with dependency injection support

Hiboot - web/cli application framework About Hiboot is a cloud native web and cli application framework written in Go. Hiboot is not trying to reinven

hidevops.io 179 Nov 20, 2022
Package macaron is a high productive and modular web framework in Go.

Macaron Package macaron is a high productive and modular web framework in Go. Getting Started The minimum requirement of Go is 1.6. To install Macaron

Macaron 3.3k Nov 17, 2022
A high productivity, full-stack web framework for the Go language.

Revel Framework A high productivity, full-stack web framework for the Go language. Current Version: 1.0.0 (2020-07-11) Supports go.mod package managem

Revel Framework 12.8k Nov 24, 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