There is no real good framework and anybody can write a trie based router in 2 hours:

https://vluxe.io/golang-router.html

However, Go ecosystem is starting to look interesting library-wise, as long as your project doesn't involve enterprise integration with legacy XML services or SOAP, because Go sucks at mostly anything XML.

For templating I use Jet because the standard templating library is too basic for professional use https://github.com/CloudyKit/jet .

I don't use ORM, I use https://github.com/Masterminds/squirrel for query building and https://github.com/jmoiron/sqlx which helps deals with row<=>struct conversion. For database migrations, I use https://github.com/rubenv/sql-migrate , but if you need an ORM gorm https://github.com/jinzhu/gorm is OK if you do code first and sqlboiler https://github.com/volatiletech/sqlboiler is OK if you do database first.

For session handling I use scs github.com/alexedwards/scs , for converting form encoded data to go structs I use github.com/gorilla/schema, for logging I use zap https://github.com/uber-go/zap. For managing roles in an app I use either the voter pattern https://symfony.com/doc/current/security/voters.html in simple cases or casbin github.com/casbin/casbin . For background jobs I used https://github.com/gocraft/work and https://github.com/gocelery/gocelery , for caching i just use redis https://github.com/go-redis/redis , for data validation I used https://github.com/asaskevich/govalidator or https://github.com/go-ozzo/ozzo-validation . For sending mails to customers I used https://github.com/go-gomail/gomail

If i need html forms, I first describe form elements as a struct then write form helpers in jet templating to display them like that:

type LoginForm struct {
Login, Password string
Form
}

func (form *LoginForm) validate(r *http.Request) error {
r.ParseForm()
form.Decoder().Decode(form, r.Form)
form.Errors = map[string][]string{}
if err := (requiredValidator{}).validate(form.Login); err != nil {
form.Errors["Login"] = append(form.Errors["Login"], err.Error())
}
if err := (requiredValidator{}).validate(form.Password); err != nil {
form.Errors["Password"] = append(form.Errors["Password"], err.Error())
}
return form.getErrors()
}
func (form LoginForm) LoginFormView() LoginFormView {
return LoginFormView{Fields: []Field{
{Name: "Login", Label: "Email", Type: "text", Value: form.Login, Required: true, Errors: form.Errors["Login"]},
{Name: "Password", Label: "Password", Type: "password", Value: form.Password, Required: true, Errors: form.Errors["Password"]},
{Type: "submit", Value: "Submit", Required: true},
{Type: "reset", Value: "Reset", Required: true},
}, Method: "POST", Name: "LoginForm"}
}

Then I can just write an helper in jet to display the the form view:

{* tag attributes *}
{{ block attributes() }}
{{range .}}
{{.Key}}="{{.Value}}"
{{end}}
{{ end }}
{* form field *}
{{block field()}}
<label>
{{.Label}}
<br/>
{{if .Type == "textarea" }}
{* textarea *}
<textarea name="{{.Name}}" {{ yield attributes() .Attributes }} >{{.Value}}</textarea>
{{ else if .Type == "select" }}
{* select *}
<select name="{{.Name}}" {{yield attributes() .Attributes }}>
{{ range .Options }}
<option value="{{.Value}}" {{ if .Selected }} selected {{ end }}>{{.Label}}</option>
{{ end }}
</select>
{{ else }}
{* basic input *}
<input type="{{.Type}}" name="{{.Name}}" {{ if isset(.Value) }} value="{{.Value}}" {{ end }}
{{ yield attributes() .Attributes }} {{ if .Checked == true }} checked {{end}} />
{{ end }}
</label>
{{end}}
{* form template *}
{{block form()}}
<form action="{{.Action}}" name="{{.Name}}" method="{{.Method}}">
<fieldset>
{{ range .Fields }} {{yield field() .}} {{end}}
</fieldset>
</form>
{{end}}

This is the exact app structure I use to deal with dependencies and filters :

https://medium.com/statuscode/how-i-write-go-http-services-a...