Q:

Idiomatic way to validate structs in Go? 

I need to validate that a struct value is correct and this means I need to check every field individually, which is easy for a small number of small structs but I was wondering if there's a better way to do it.  Here's how I'm doing it right now. 
type Event struct {
    Id     int
    UserId int
    Start  time. Time
    End    time. Time
    Title  string
    Notes  string
}

func (e Event) IsValid() error {
    if e.Id <= 0 {
        return errors. New("Id must be greater than 0")
    }
    if e.UserId <= 0 {
        return errors. New("UserId must be greater than 0")
    }
    if e.End <= e.Start {
        return errors. New("End must be after Start")
    }
    if e.Start < time. Now() {
        return errors. New("Cannot create events in the past")
    }
    if e.Title == "" {
        return errors. New("Title cannot be empty")
    }
    return nil
}

Is this the idiomatic way to validate the values of fields in a struct?  It looks cumbersome. 

A:

I don't see any other way to do this quickly.  But I found a go package which can help you with this: https://github.com/go-validator/validator
The README file gives this example:
type NewUserRequest struct {
    Username string `validator:"min=3,max=40,regexp=^[a-zA-Z]$"`
    Name string     `validator:"nonzero"`
    Age int         `validator:"min=21"`
    Password string `validator:"min=8"`
}

nur := NewUserRequest{Username: "something", Age: 20}
if valid, errs := validator. Validate(nur); ! valid {
    // values not valid, deal with errors here
}

A:

Doing that way you will end up writing a lot of duplicate code for each of your model. 
Using a library with tags comes with its own pros and cons.  Sometimes is easy to start but down the road you hit the library limitations. 
One possible approach is to create a "Validator" that its only responsibility is to keep track of the possible errors inside an object. 
A very approximate stub of this idea:
http://play.golang.org/p/buBUzk5z6I
package main

import (
    "fmt"
    "time"
)

type Event struct {
    Id     int
    UserId int
    Start  time. Time
    End    time. Time
    Title  string
    Notes  string
}

type Validator struct {
    err error
}

func (v *Validator) MustBeGreaterThan(high, value int) bool {
    if v.err ! = nil {
        return false
    }
    if value <= high {
        v.err = fmt. Errorf("Must be Greater than %d", high)
        return false
    }
    return true
}

func (v *Validator) MustBeBefore(high, value time. Time) bool {
    if v.err ! = nil {
        return false
    }
    if value. After(high) {
        v.err = fmt. Errorf("Must be Before than %v", high)
        return false
    }
    return true
}

func (v *Validator) MustBeNotEmpty(value string) bool {
    if v.err ! = nil {
        return false
    }
    if value == "" {
        v.err = fmt. Errorf("Must not be Empty")
        return false
    }
    return true
}

func (v *Validator) IsValid() bool {
    return v.err ! = nil
}

func (v *Validator) Error() string {
    return v.err. Error()
}

func main() {
    v := new(Validator)
    e := new(Event)
    v.MustBeGreaterThan(e. Id, 0)
    v.MustBeGreaterThan(e. UserId, 0)
    v.MustBeBefore(e. End, e.Start)
    v.MustBeNotEmpty(e. Title)
    if ! v.IsValid() {
        fmt. Println(v)
    } else {
    fmt. Println("Valid")
    }
}
package main

import (
    "fmt"
    "time"
)

type Event struct {
    Id     int
    UserId int
    Start  time. Time
    End    time. Time
    Title  string
    Notes  string
}

type Validator struct {
    err error
}

func (v *Validator) MustBeGreaterThan(high, value int) bool {
    if v.err ! = nil {
        return false
    }
    if value <= high {
        v.err = fmt. Errorf("Must be Greater than %d", high)
        return false
    }
    return true
}

func (v *Validator) MustBeBefore(high, value time. Time) bool {
    if v.err ! = nil {
        return false
    }
    if value. After(high) {
        v.err = fmt. Errorf("Must be Before than %v", high)
        return false
    }
    return true
}

func (v *Validator) MustBeNotEmpty(value string) bool {
    if v.err ! = nil {
        return false
    }
    if value == "" {
        v.err = fmt. Errorf("Must not be Empty")
        return false
    }
    return true
}

func (v *Validator) IsValid() bool {
    return v.err ! = nil
}

func (v *Validator) Error() string {
    return v.err. Error()
}

func main() {
    v := new(Validator)
    e := new(Event)
    v.MustBeGreaterThan(e. Id, 0)
    v.MustBeGreaterThan(e. UserId, 0)
    v.MustBeBefore(e. End, e.Start)
    v.MustBeNotEmpty(e. Title)
    if ! v.IsValid() {
        fmt. Println(v)
    } else {
    fmt. Println("Valid")
    }
}

You can then create your Validate method and use the same code:
func (e *Event) IsValid() error {
        v := new(Validator)
    v.MustBeGreaterThan(e. Id, 0)
    v.MustBeGreaterThan(e. UserId, 0)
    v.MustBeBefore(e. End, e.Start)
    v.MustBeNotEmpty(e. Title)
    return v.IsValid()
}

A:

To help anyone else that may be looking for another validation library I created the following https://github.com/bluesuncorp/validator
It addresses some issues that other plugins have not implemented yet that others in this thread had mentioned such as:

Returning all validation errors
multiple validations per field
cross field validation ex.  Start > End date

Inspired by several other projects including the accepted answer of go-validator/validator

