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, is built around the concept of controllers and actions. However, as opposed to Revel and other high level frameworks Goal does not use runtime reflection and does not require your app to import monolithic dependencies.

Instead Goal is implemented in a form of independent tools that may be used with go generate. That allows us to achieve type safety, minimalism of dependencies, compatability with the standard library, and productivity for the end-developers. At the same time Goal is very customizable (you can bring your own router, template system, and any other component). But that's without prejudice to the easiness and seamless of experience thanks to good defaults.

Getting Started

  1. Install Goal:

     go get -u github.com/goaltools/goal
    
  2. Create a new skeleton application:

     goal new github.com/$username/$project
    
  3. Start a watcher / task runner:

     goal run github.com/$username/$project
    

Documentation

All goal generate * tools may be used with go generate.

Status

Proof of Concept: not ready for use in the wild. Working on: splitting the project into independent repos.

GoDoc Build Status Coverage Status Go Report Card

License

Distributed under the BSD 2-clause "Simplified" License unless otherwise noted.

Comments
  • handlers folders disappear?

    handlers folders disappear?

    When i execute "goal new mygoal" , it is ok.

    But when i execute "goal run mygoal", in the "mygoal/assets", the "handlers" subdirectory and its files are disappeared? before it, the handlers subdirecory and its files are exists!
    My "$GOPATH/src" is ok! so the errors are the following: ``

     Running `goal generate handlers --input ./controllers/ --output ./assets/handlers/`...
    
    Removing "./assets/handlers/" directory if already exists...
    
    Error: path "F:\golang/src/mygoal\controllers" is not inside "$GOPATH/src".
    
    Failed to run a command "go build -o ./bin/run.exe mygoal", error: exit status 1
    
    Preparing "./bin/run.exe"...
    
    Starting a new instance of `./bin/run.exe`...
    
    Adding "./views/" to the list of watched directories...
    
    Failed to start a command `./bin/run.exe`, error: exec: "./bin/run.exe": file does not exist.
    

    `` where is the "run.exe"? what's wrong with it?

  • How to get the controller's name and action?

    How to get the controller's name and action?

    How to get the controller's name and action? How to get all the names and actions but "Before,After,Initially,Finnally" I want to intercept some actions for authority.

  • Document every tool

    Document every tool

    Manual lives here. The docs are for MVP but they are still valid. Every tool here must have their own README.md as follows:

    • tools/
      • run/
        • main.go
        • ...
        • README.md
      • new/
        • main.go
        • ...
        • README.md
      • ...

    And we can have a list and short descriptions of all supported tools in the root README.md.

  • Moving project to its own organization: a new name is needed

    Moving project to its own organization: a new name is needed

    It is both possible to:

    • Come up with the idea of an organization name but use the same toolkit name;
    • Rename the toolkit, too.

    My proposals are:

    • goaltools/goal (goaltools.com domain is available)
    • goalproject/goal (.com, .org, .net domains are taken)
    • ~~goaltech/goal (both GH username goaltech and domains are taken)~~
    • Rename back to sunplate (we have sunplate.club domain)

    Other options are welcome.

  • Routes generation

    Routes generation

    Routes in Goal

    Goal's routes package in the auto generated skeleton app is nothing more than a global List variable and calls to the default router:

    var List = r.Routes{
        r.Get("/some/path", h.SomeController.SomeAction),
        r.Post(...),
        ...
    }
    
    • Advantages of this approach are:
      1. Router of end-developer's choice, nothing Goal specific.
      2. User can modify routes package and write there whatever code he/she needs.
      3. Type safe (e.g. r.Get will be compiled, r.Gte wont be; h.Controller.Action will, h.Controller.Atcion wont, etc).
    • Disadvantages:
      1. End-developer has to switch between controller file and routes. You're adding a new action, then have to open routes.go to reflect that addition.
      2. We need to implement reverse routes generation (read more about reverse routes in Revel). That means our parser will have to know how to handle the routes.go (so we'll have to introduce Goal specific code or convention).

    Proposal

    Use annotation like syntax. E.g. in Bottle.py there is:

    @route('/hello/<name>')
    def greet(name):
        return template('<b>Hello {{name}}</b>!', name=name)
    

    There are no annotations in Go, but other tools such as go generate and go build use tags in comments. That's what we can do, too:

    //@get /hello/:name
    func (c App) Greet(name string) http.Handler {
        c.Context = name
        return c.Render()
    }
    

    Import of actions

    Controllers end-developer embeds may include actions with routes. Those can be prefixed as follows:

    type App struct {
        // ControllerWithErrorMsgActions contains Error404 action
        // with "@get /404".
        pkg.ControllerWithErrorMsgActions `@route:"/errors/"`
    }
    
    //
    // The code above is equivalent to writing right in this file:
    //
    
    //@get /errors/404
    func (c *App) Error404() http.Handler {
        ... // Whatever Error404 of ControllerWithErrorMsgActions controller does.
    }
    

    Result of generation

    It is supposed the generated code will be similar to:

    var Routes = []struct{
        Type, Pattern string
        Handler http.Handler
    }{
        {Type: "GET", Pattern: "/hello/:name", Handler: h.App.Greet}
        ...
    }
    

    This Routes then can be used by the router (after importing the package where it's located).

    For now the variable should be located within generated handlers package (as it is easy to implement). After MVP version will require generation of a new routes package in ./assets/.

    Reverse routing

    We'll use controllers to generate both routes and reverse routes. A new issue must be open for the latter.

  • Static file default paths

    Static file default paths

    The default path for static files are at example.com/static/styles/app.css. Maybe it should be at root directory example.com/styles/app.css.

    If someone adds a robots.txt file in the static folder it would be at example.com/static/robots.txt. I read that the robots.txt file should be at root example.com/robots.txt

    I also think it would be nice to follow twitter bootstrap and html5 boilerplate naming of javascript and css folders. They use /css/main.css and /js/main.js

  • A new format of task runner's configuration file

    A new format of task runner's configuration file

    Goal's run tool uses YAML for its configuration file. The file is described here. However, I'd like to replace it by something else. I want all code including dependencies to meet the following requirements (apart from the general quality of the library):

    1. gofmt-ed with -s flag;
    2. golint-ed
    3. checked with go vet. go-yaml doesn't meet those requirements and that is the only Go implementation of YAML that is active and maintained.

    I have played with different formats. Not sure about XML. But JSON doesn't work, comments are not supported and the whole config looks very difficult to read and understand with all those ", ,, and {} that could be omitted. It is also possible to use a custom format. Here is one I have developed right for this use-case.

  • Multi-domain / Sub-domains?

    Multi-domain / Sub-domains?

    In httprouter, it supportes Multi-domain / Sub-domains? https://github.com/julienschmidt/httprouter#web-frameworks-based-on-httprouter Could goal support it?

  • Define high level goals

    Define high level goals

    Let's define the high level goals of the project. What are we trying to achieve? What are the priorities?

    Can it be more than a traditional (by traditional I mean HTML template system as V) MVC framework? Probably, like Meteor, Volt, Webalchemy. Should it? Or we can just make sure it works good with Angular, React, and whatever is fashionable now.

    The code generation we are relying on is pretty powerful and we can do a lot of cool things. We just need to decide what cool things we want.

    And to the question of positioning: is it a framework or toolkit? It is implemented in a form of separate tools. Every one is independent and can be used on its own. But on the other hand all of the tools play nicely with each other and form a single framework. So, how should we call it (need to know as it is used a lot in the comments and docs)? I have started with "toolkit" but recently switched to "framework".

  • fix new Controller instance is failed

    fix new Controller instance is failed

    old code is

    func (t tControllers) newC(w http.ResponseWriter, r *http.Request, ctr, act string) *contr.Controllers {
        // Allocate a new controller. Set values of special fields, if necessary.
        c := &contr.Controllers{}
    
        // Allocate its parents. Make sure controller of every type
        // is allocated just once, then reused.
        c.Templates = c.Errors.Templates
        c.Errors = &c5.Errors{}
        c.Static = &c3.Static{}
        c.Sessions = &c2.Sessions{
    
            Request: r,
    
            Response: w,
        }
        c.Requests = &c1.Requests{
    
            Request: r,
    
            Response: w,
        }
        c.Global = &c0.Global{
    
            CurrentAction: act,
    
            CurrentController: ctr,
        }
        c.Errors.Templates = &c4.Templates{}
        c.Errors.Templates.Requests = c.Requests
        c.Errors.Templates.Global = c.Global
        c.Templates.Requests = c.Requests
        c.Templates.Global = c.Global
    
        return c
    }
    

    new code is

    
    func (t tControllers) newC(w http.ResponseWriter, r *http.Request, ctr, act string) *contr.Controllers {
        // Allocate a new controller. Set values of special fields, if necessary.
        c := &contr.Controllers{}
    
        // Allocate its parents. Make sure controller of every type
        // is allocated just once, then reused.
        c.Templates = &c4.Templates{}
        c.Errors = &c5.Errors{}
        c.Static = &c3.Static{}
        c.Sessions = &c2.Sessions{
    
            Request: r,
    
            Response: w,
        }
        c.Requests = &c1.Requests{
    
            Request: r,
    
            Response: w,
        }
        c.Global = &c0.Global{
    
            CurrentAction: act,
    
            CurrentController: ctr,
        }
        c.Errors.Templates = c.Templates
        c.Templates.Requests = c.Requests
        c.Templates.Global = c.Global
    
        return c
    }
    
  • Fix tests of generate/handlers tool

    Fix tests of generate/handlers tool

    internal/reflect returns functions/methods in a random order that's why tests of tools/generate/handlers fail randomly (in 50% of cases restart of tests is necessary). Make sure the issue is resolved when start working on #3.

  • Allocate parent controllers just once

    Allocate parent controllers just once

    Intro

    There is a controller with its special action:

    type GrandParent struct {
        Context map[string]interface{}
    }
    
    func (c *GrandParent) Before() http.Handler {
        println("This is GrandParent")
        c.Context = map[string]interface{}{}
    }
    

    The controller above is embedded by a number of other controllers.

    type Parent1 struct {
        *GrandParent
    }
    type Parent2 struct {
        *GrandParent
    }
    

    Those controllers are embedded by our main controller.

    type Child struct {
        *Parent1
        *Parent2
    }
    
    func (c *Child) Index() http.Handler {
    }
    

    Problem

    The problem is the GrandParent controller will be allocated twice, meaning c.Parent1.GrandParent != c.Parent2.GrandParent. The output of the GrandParent's Before will be:

    This is GrandParent
    This is GrandParent
    

    As a result, we cannot share a context between controllers of different levels of embedding.

    Use-case

    This is the problem I've faced trying to implement #39. There is controllers/errors controller that is responsible for rendering error pages. We embed it in our main controller and mount its actions to * /errors:

    type Controllers struct {
        errors.Errors `@route:"/errors"`
    }
    

    Now if we want to pass some value to the actions of that Errors controller it doesn't work:

    func (c *Controllers) Before() http.Handler {
        c.Context["someKey"] = "someValue"
    }
    

    Because, Context of Controllers and Context of Errors are different instances. But they must be pointers to the same object.

    Expectations

    A single allocation per object per request. Special (Before and After) actions must be called just once: Parents must have priority over their Children.

  • Split `generate handlers` into multiple tools

    Split `generate handlers` into multiple tools

    Tool generate handlers is getting too complex. It should be split into multiple ones:

    • scan controllers (name TBD) - parses controllers and dependencies, serializes result and saves it as .json (or some other format that is TBD).
    • generate handlers - reads generated .json and creates a handlers package.
    • generate routes - reads generated .json and creates routes package.
    • generate reverse routes - reads generated .json and creates routes/reverse package.
  • Add some more functions?

    Add some more functions?

    1.When visit the static page ,such as http://localhost:8080/static/index.html,It still execute the Controller's All Initially() and Before() function? if visit the static page ,it will execute these function many time,because the index.htm include some css and js and jpg? Maybe another usage is that we can intercept the static file. Maybe should make a switch for it?

    the route for static is: r.Get("/static/*filepath", http.StripPrefix("/static/", http.FileServer(http.Dir("./static")), ).ServeHTTP),

    2.There are still not RenderXML and RenderFile methods.

    3.Have a flash function like revel's flash function? and the compressionTypes,cache.....?

    4.https? http2?

  • Wiki on web development in Go language

    Wiki on web development in Go language

    We need to work on the quality of our docs:

    • [ ] Better layout and navigation
    • [ ] Update things that are not up-to-date
    • [ ] Cover things that are missing (e.g. default controllers, goal new listing, etc.)

    Moreover, I propose to change the target audience we are trying to address. Not the Go web developers but those who have no experience with Go language and/or Web Development at all. The former is a pretty small group with already shaped preferences and tastes. We can attract fresh blood instead: people from other stacks and backgrounds.

    What we need:

    • [ ] More general purpose articles. E.g. about installation of Go and configuration of GOPATH with screenshots (on Linux / Windows / MacOS) and all
    • [ ] Screencasts
    • [ ] Better quality of content, more details, do not assume user is an expert
    • [ ] Tutorials
  • Feature: autoform

    Feature: autoform

    Creation and validation of forms is IMO the most boring part of web-development. Let's make it fun again. The use-case is:

    1. End-developer describes their data once.
    2. Goal toolkit generates the code that can be used for both form generation and its validation.

    We could possibly use struct tags for that. E.g.:

    type User struct {
        Name        string `autoform:"required=true,minsize=2,maxsize=100"`
        Email       string `autoform:"email=true"`
        Age         int    `autoform:"min=13,max=150"`
        CountryCode string `autoform:"length=2"`
        CardNumber  string
    }
    

    Though this is not type safe. Alternatively, we can apply a "magic methods" approach we use for the controllers.

    Related functionality in other frameworks

    1. https://docs.djangoproject.com/en/1.7/topics/forms/modelforms/
    2. https://www.playframework.com/documentation/2.1.0/JavaForms
  • Docker support

    Docker support

    Goal gives a error while trying to build a docker image with this dockerfile. It works if the project files are on a public github repo.

    fatal: could not read Username for 'https://github.com': No such device or address package github.com/davidhunter/goal-sample/server: exit status 128

    FROM golang:onbuild
    EXPOSE 8080
    

    Then their is another issue where I can't connect to it outside a container.

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

Nov 14, 2022
A high level web-framework for Go

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 Documentatio

Dec 24, 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

Apr 29, 2021
Golang CTF framework and exploit development module

Golang CTF framework and exploit development module

Dec 18, 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

Sep 10, 2022
:bullettrain_side: High-performance web server for Go.
: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 -

Dec 8, 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

Dec 15, 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

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

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

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

Jan 2, 2023
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

Dec 7, 2022
A lightweight RESTful web framework for Go
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

Dec 12, 2022
Fast and Reliable Golang Web Framework
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

Dec 18, 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

Nov 17, 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

Dec 29, 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

Dec 9, 2022
The web framework for Golang
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:

Dec 24, 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

Feb 11, 2021
Community built data connectors and processors for Spice.ai

data-components-contrib Community built data connectors and processors for Spice.ai The vision for data-components-contrib is a community-driven libra

Sep 24, 2022