Golang: Reverse ISOWeek, get the date of the first day of ISO week

If you work with weeknummers, you can find the weeknumber of a date with the Golang function time.ISOWeek. However you wish to get the first date of a week, there is no such function in Google Go. So let’s write it our selfs:

func FirstDayOfISOWeek(year int, week int, timezone *time.Location) time.Time {
date := time.Date(year, 0, 0, 0, 0, 0, 0, timezone)
isoYear, isoWeek := date.ISOWeek()

// iterate back to Monday
for date.Weekday() != time.Monday {
date = date.AddDate(0, 0, -1)
isoYear, isoWeek = date.ISOWeek()
}

// iterate forward to the first day of the first week
for isoYear < year {
date = date.AddDate(0, 0, 7)
isoYear, isoWeek = date.ISOWeek()
}

// iterate forward to the first day of the given week
for isoWeek < week {
date = date.AddDate(0, 0, 7)
isoYear, isoWeek = date.ISOWeek()
}

return date
}

Golang html/template range: access out of loop variable

When you use range in a Golang html/template the “.” variable changes to the current object from the range. We can however still access to old “.” variable with “$”:


{{range $index, $emp := .employees}}
{{ $emp.name }}
{{ msg $ "btn_show" }}
{{ end }}

Building a Golang web application with Revel

Google Go is an excelent language for building (compiled) web applications. We could start building a Golang web application from scratch, but like with other languages you can start off faster with an existing framework.

I have tried several diffent frameworks, but many of them are still inmature and often lack documentation. The best and easiest to use web framework that I found so far is Revel, so in this tutorial we will use Revel.

In this tutorial we assume you already have Go installed. If this is not the case, please install it first using the following instructions: http://golang.org/doc/install

Installing the Revel framework

Get Revel with the following command:

go get github.com/revel/revel
go get github.com/revel/cmd/revel

With this command Go will download and install Revel on your machine. The first command installs the framework and the second command the commandline tool.

Creating your Revel project

Really there is not much to it, revel generates almost all automatically:

revel new myapp

Now open the application in your code editor, I use Sublime Text, but you can use any editor of your choice.

Models missing

If you are familiar with MVC frameworks, you may have noticed that de models directory is missing. This is because Revel does not have an integrated ORM tool. If you need database access you can use any ORM library of your choice (or none at all). You could for example use gorp als a ORM library.

In this example we will use gorp with MySQL, but it should not be to hard to change this.

Creating a database connection

To be able the access the database quickly when the web request start coming in, we need to setup the database connection when the application is started. Let’s do this from a file called init.go in the folder “app/models”. If this folder does not exist, create it.  With the following code:

package models
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"github.com/coopernurse/gorp"
"log"
) 
// Global database references
var db *sql.DB
var dbmap *gorp.DbMap
// Database settings
var db_name = "mydb"
var db_user = "myuser"
var db_pw = "mypw"
// Create database connection
func Init_DB() {
var err error
db, err = sql.Open("mysql", db_user + ":" + db_pw + "@tcp(127.0.0.1:3306)/" + db_name)
dbmap = &gorp.DbMap{Db: db, Dialect: gorp.MySQLDialect{"InnoDB", "UTF8"}}
if err != nil {
log.Println("Failed to connect to database: ")
log.Panic(err)
} else {
err = db.Ping()
if err != nil {
log.Println("Failed to ping database: ")
log.Panic(err)
} else {
log.Println("Database connected.")
}
}
_ = dbmap.AddTableWithName(Employee{}, "employees").SetKeys(false, "Id")
dbmap.CreateTablesIfNotExists()
}

First we import the database drivers and define global database references (within the models package).

You will need to modify the database settings so that the correct database and user information is used. This code assumes that the database is on the localhost.

After that we try to connect to the database and verify that the connection is working.

The last lines are to map our models (structs) to the database tables. We included here the option to create the table if it does not exist. This maybe easy for development and testing, but is not required.

Revel does not load the models/init.go file automatically, so we will have to add this to the app/init.go file:

Make sure that the models package is imported:

import (
"github.com/revel/revel"
"myapp/app/models"
)

Now let’s call the Init_DB function:

func init() {
// Filters is the default set of global filters.
revel.Filters = []revel.Filter{
revel.PanicFilter, // Recover from panics and display an error page instead.
revel.RouterFilter, // Use the routing table to select the right Action
revel.FilterConfiguringFilter, // A hook for adding or removing per-Action filters.
revel.ParamsFilter, // Parse parameters into Controller.Params.
revel.SessionFilter, // Restore and write the session cookie.
revel.FlashFilter, // Restore and write the flash cookie.
revel.ValidationFilter, // Restore kept validation errors and save new ones from cookie.
revel.I18nFilter, // Resolve the requested language
HeaderFilter, // Add some security based headers
revel.InterceptorFilter, // Run interceptors around the action.
revel.CompressFilter, // Compress the result.
revel.ActionInvoker, // Invoke the action.
}
// register startup functions with OnAppStart
// ( order dependent )
revel.OnAppStart(models.Init_DB)
// revel.OnAppStart(FillCache)
}

Creating a model

Now we have a connection to MySQL, let make a simple model to access the employees table:

package models
import (
"log"
"time"
)
type Employee struct {
Id int 
First_name string 
Last_name string 
}
func FindEmployee(number int) (bool, *Employee) {
obj, err := dbmap.Get(Employee{}, number)
emp := obj.(*Employee)
if err != nil {
log.Print("ERROR findEmployee: ")
log.Println(err)
}
return (err == nil), emp
}

Probably you will need more functions, but this should be enough to get you started.

Testing your application

To start your web application:

revel run myapp

After this you should be able to see your web application at: http://localhost:9000.