I am currently starting with Go and have already dug into the dos and don'ts regarding package naming and workspace folder structure.
Nevertheless, I am not quite sure how to properly organize my code according to the Go paradigm.
Here is my current structure example as it resides in $GOPATH/src:
github.com/myusername/project
|-- main.go
+-- internal
+---- config
|------ config.go
So i have the project called project which uses the config package which, in turn, is specialized in a way that it should only be used by project. Hence, I do not want it under github.com/myusername/config, right?
The question now is, is it "good" to use the internal package structure or should I instead put my project specific packages under github.com/myusername/$pkgname and indicate somehow that it belongs to project (e.g. name it projectconfig)?
If your project produces one single program then the most common structure is the one you mentioned.
If your project produces more than one program the common practice is using a structure like this:
<project>/
cmd/
prog1/
main.go
prog2/
main.go
If your project exposes go code as library for third party consumption the most common structure is using the project's root dir to expose the domain model and API.
<project>/
model.go
api.go
This is for third party code to just import "github.com/user/project" and have the model and api available.
Is common to see second and third options combined.
Also is considered good practice to have packages for encapsulating dependencies usage. E.g. suppose your project uses the elastic search client
<project>/
cmd/
prog1/
main.go
elastic/
impl.go
dao.go
model.go
So in dao.go you define the dao's API and then in elastic/impl.go you (import elastic library, domain modal and) define the implementation of DAO in terms of elastic. Finally you import everything from main.go which produces the actual program.
See this great and short presentation about this issue.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
We don’t allow questions seeking recommendations for books, tools, software libraries, and more. You can edit the question so it can be answered with facts and citations.
Closed 4 years ago.
Improve this question
I want to build an API based application using GO and MongoDB. I'm from Asp.net MVC background. Probably if I make an architecture with MVC web application things to be consider are
Separation of concerns(SoC)
DataModel
BusinessEntities
BusinessServices
Controllers
Dependeny Injection and Unity of Work
Unit Testing
MoQ or nUnit
Integration with UI frameworks
Angularjs or others
RESTful urls that enables SEO
Below architecture could be a solution for my need in MVC based appications
There are resources around the web to build Asp.Net or Java based applications, but I have not find solution to Golang application architecture.
Yes GO is different to C# or Java, but still there are Structs, Interfaces to create reusable code and a generic application architecture.
Consider above points in mind, how we can make a clean and reusable project structure in GO applications and a generic repositories for DB(Mongodb) transactions. Any web resources also a great point to start.
It depends on your own style and rules, in my company, we develop our projects this way:
Configuration is determined by environment variables, so we have a company/envs/project.sh file which has to be evaluated before service (outside the project in the image).
We add a zscripts folder that contains all extra scripts, like adding users or publishing a post. Intended to be used only for debug proposes.
Data models (entities) are in a package called project/models.
All controllers and views (HTML templates) are categorized into "apps" or "modules". We use the REST path as main group delimiter, so path /dogs goes to package project/apps/dogs and /cats to project/apps/cats.
Managers are in their separated package at project's root project/manager.
Static files (.css, .png, .js, etc.) are located at project/static/[app/]. Sometimes is required to have the optional [app/] folder, but it only happens when two apps have dashboards or conflicting file names. Most of cases you won't need to use [app/] for static resources.
Managers
We call a manager, a package that contains pure functions which helps apps to perform its task, for example, databases, cache, S3 storage, etc. We initialize each manager calling package.Startup() before we start to listen, and finalize calling package.Finalize() when program is interrupted.
An example of a manager could be project/cache/cache.go:
type Config struct {
RedisURL string `envconfig:"redis_url"`
}
var config Config
var client *redis.Client
func Startup(c Config) error {
config = c
client, err := redis.Dial(c.RedisURL)
return err
}
func Set(k,v string) error {
return client.Set(k, v)
}
in main.go (or your_thing_test.go):
var spec cache.Config
envconfig.Process("project", &spec)
cache.Startup(spec)
And in a app (or module):
func SetCacheHandler(_ http.ResponseWriter, _ *http.Request){
cache.Set("this", "rocks")
}
Modules
A module is a container of views and controllers that are isolated from other modules, using our configuration I would recommend to not create dependencies between modules. Modules are also called apps.
Each module configures its routes using a router, sub-router or what your framework provides, for example (file project/apps/dogs/configure.go):
func Configure(e *echo.Echo) {
e.Get("/dogs", List)
}
Then, all handlers live in project/apps/dogs/handlers.go:
// List outputs a dog list of all stored specimen.
func List(c *echo.Context) error {
// Note the use of models.Xyz
var res := make([]models.Dog, 0) // A little trick to not return nil.
err := store.FindAll("dogs", nil, &res) // Call manager to find all dogs.
// handle error ...
return c.JSON(200, res) // Output the dogs.
}
Finally you configure the app in main (or in a test):
e := echo.New()
dogs.Configure(e)
// more apps
e.Run(":8080")
Note: for views, you can add them to project/apps/<name>/views folder and configure them the using the same function.
Other
Sometimes we also add a project/constants and a project/utils package.
Here is what it looks like:
Note that in above sample, templates are separated from apps, thats because its a placeholder, directory is empty.
Hope it was useful. Greetings from México :D.
I've also struggled about how to structure my Go web APIs in the past and don't know any web resources that tell you exactly how to write a Go web API.
What I did was just check out other projects on Github and try out how they structured their code, for example, the Docker repo has very idomatic Go code on it's API.
Also, Beego is a RESTful framework that generates the project structure for you in a MVC way and according to their docs, it can also be used for APIs.
I've been building a web APIs in golang for a little while now.
You'll have to do some research but I can give you some starting points:
Building Web Apps with Go -- ebook
github.com/julienschmidt/httprouter -- for routing addresses
github.com/unrolled/render/ -- for rendering various forms of responses(JSON, HTML, etc..)
github.com/dgrijalva/jwt-go -- JSON Web Tokens
www.gorillatoolkit.org/pkg/sessions -- Session Management
And for reference on how some things work together in the end:
Go Web API Repo -- personal project
1. Separation of concerns (SoC)
I haven't worked with SoC directly, but I have my own pattern. You can adapt to whatever pattern (MVC, your own, etc.).
In my code, I separate my code into different packages:
myprojectname (package main) — Holds the very basic setup and configuration/project consts
* handlers (package handlers) — Holds the code that does the raw HTTP work
* models (package models) — Holds the models
* apis (NOT a package)
- redis (package redis) — Holds the code that wraps a `sync.Pool`
- twilio (package twilio) — Example of layer to deal with external API
Notes:
In each package other than main, I have a Setup() function (with relevant arguments) that is called by the main package.
For the packages under the apis folder, they are often just to initialize external Go libraries. You also can directly import existing libraries into the handlers/models without an apis package.
I setup my mux as an exported global in the handlers package like this...
Router := mux.NewRouter()
...and then create a file for each URL (different methods with the same URL are in the same file). In each file, I use Go's init() function, which is ran after global variables are initialized (so it's safe to use the router) but before main() is ran (so it's safe for main to assume everything has been setup). The great thing about init() is that you can have as many of those methods as you want in a single package, so they automatically get ran when the package is imported.
Main then imports myprojectname/handlers and then serves the handlers.Router in main.
2. Dependency Injection and Unity of Work
I haven't worked with Unity of Work, so I have no idea of possible Go implementations.
For DI, I build an interface that both the real object and the mock objects will implement.
In the package, I add this to the root:
var DatabaseController DatabaseControllerInterface = DefaultController
Then, the first line of each test I can change DatabaseController to whatever that test needs. When not testing, the unit tests should not be ran, and it defaults to DefaultController.
3. Unit Testing
Go provides a built in testing with the go test package command. You can use go test --cover to also emit a coverage percent. You can even have coverage displayed in your browser, highlighting the parts that are/aren't covered.
I use the testify/assert package to help me with testing where the standard library falls short:
// something_test.go
//
// The _test signifies it should only be compiled into a test
// Name the file whatever you want, but if it's testing code
// in a single file, I like to do filename_test.go.
package main
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestMath(t *testing.T) {
assert.Equal(t, 3+1, 4)
}
4. Integration with UI frameworks
I haven't seen any for Angular. Although I haven't used it, Go has a good template engine built into the standard lib.
5. RESTful URLs that enables SEO
Again, I can't help you here. It's up to you: send proper status codes (don't send a 200 with a 404 page as you'll get docked for duplicate pages), don't duplicate pages (pay attention to google.com/something vs google.com/something/; hopefully your framework will not mess this up), don't try to trick the search engine, and so on.
To my mind Go webapp project folder on production server can looks like on your picture just much simpler. Nothing special in assets structure - Static, Templates, Content, Styles, Img, JSlibs, DBscripts etc. usual folders. Nothing special in WebAPI - as usual you design which URI will respond required functionality and route requests to handlers accordingly. Some specifics - many gophers don't believe in MVC architecture, it's up to you surely. And you deploy one staticaly linked executable without dependencies. In your development environment you structure yours and imported/vendored sorce files in $GOPATH as in stdlib done but deploy only one executable in production environment, sure with static assets needed. You can see how to orginize Go source packages just in stdlib. Having just one executable what would you structure on production?
I am trying to use a shared controller from a module in my app, but I'm not really sure how to do it. Here's what I want to do:
I have two revel apps, a frontend and backend app. The frontend app is used to show the user-facing site, and the backend app is for admin stuffs.
I created a special controller to connect to database as per the booking sample.
I want both the frontend and backend app to use the same controller, to minimize redundancy.
From the sample, when you want to have one controller database, it roughly translate to this:
type DBController {
*revel.Controller
}
type App {
DBController
}
This works when I want to have only 1 app, but when I want to share the controller to another app, I can't import DBController to the app.
Things I've Tried
I tried moving DBController to its own package, and then importing that and inherit from it directly:
// in db.go
package controllers
// import and stuffs
type DBController {
*revel.Controller
}
// in app.go
package controllers
import (
dbc "site.com/modules/controllers"
)
type App struct {
dbc.DBController
// *dbc.DBController
}
This gives me a panic error stating that the route is not found:
panic: Route validation error (in /app/path/routes:7):
revel/controller: failed to find controller App
in both inheriting with and without pointer.
I've also tried Revel's module, with the same code, but different directory and importing via config:
// app.conf
modules.dbcontroller=site.com/modules/dbcontroller
And then in app.go:
type App struct {
DBController
}
But it still didn't work with the same error as before. I'm pretty convinced that the right route is by using module, since the documentation said (emphasis mine):
Modules are packages that can be plugged into an application. They allow sharing of controllers, views, assets, and other code between multiple Revel applications or from third-party sources.
A module should have the same layout as a Revel application’s layout. The “hosting” application will merge it in as follows:
Any templates in module/app/views will be added to the Template Loader search path
Any controllers in module/app/controllers will be treated as if they were in your application.
etc..
But I'm not sure how I can share and derive my controller from here.
TL; DR
How do I share controller in Revel so that I can inherit a controller from other module, roughly like:
import dbc "site.com/modules/dbcontroller"
type App struct {
dbc.DBController
}
so that DBController can be used with several revel apps? Thank you very much.
I am not an authority, but I will make a few observations that might help even though I do not have a complete answer for you.
The first thing about your question that struck me is the use of the term "inherit" -- Go does not support inheritance. It does support embedding. I might have written the question subject as "Reuse controller from module in Revel framework.
Second, I wonder if you are trying to reuse a Revel module between two separate Revel applications or if you are trying to reuse code from a module in two separate parts of one Revel application that just happens to have a front end and a back end. A quick read of the reveal framework makes me think modules were designed for the former, not the latter.
Third, I wonder if perhaps you are confusing files with packages. It was not obvious to me when learning Go that one package can span multiple files.. if the same declaration of "package controller" exists in two files such as db.go and app.go, they are still in the same package.
I'm currently following the Laravel Package documentation, which uses the workbench tool to create a standard package tree consisting of controller, config, views, etc. folders. Basically, most folders you would get in a standard Laravel app tree.
However, I had a couple of questions:
Why is the models folder absent here? (though the same goes for tests and commands)
Should I just create the folder myself and add it to the composer.json autoload classmap?
What classes should live inside src/<Namespace>/<PackageName>? I have noticed that a ServiceProvider is automatically created here, but I can imagine most other files just existing in the standard package directories.
Wockbench represents just a tool for creating other tools, that is triggered through CLI. Workbench is very abstract concept.
Model folder is absent simply because you don't need model in every new package. For example, if you are creating middleware package or you own filter package.
Every new class can be added to package dependent on its purpose and responsibility. It can be done in more then one way.
Classes that are general enough to go into every package are:
Package Service Provider
Facade
Basic Class
But it is not a black box. Consider for example request class - it is bound very early in the application life cycle, so no provider is needed.
I would like to be able to build functionality for my application in a plugin style system for a couple reasons:
New projects can choose which plugins are necessary and not have code for functionality that's not needed
Other developers can build plugins for the system without needing too much knowledge of the core workings.
I'm not really sure how to go about implementing this. I would like to have a plugins folder to host these separately but I guess my questions are:
How do plugins interact with the core system?
How does the folder structure work? Would each hold the standard MVC structure: controllers, services, models, views, etc?
I guess if anyone has a tutorial or some documentation relating to this technique that would be helpful. I've done a bit of searching but it's all a little too closely related to the actual code they're working with instead of the concept and I hadn't found anything specifically related to nodejs.
I suggest an approach similar to what I've done on the uptime project (https://github.com/fzaninotto/uptime/blob/master/app.js#L46):
trigger application events in critical parts of your application
add a 'plugins' section in the applicaition configuration
each plugin name must be a package name. The plugin packages should return either a callback, or an object with an init() function.
either way, inject to the plugins the objects they will need to run (configuration, connections, etc) when calling init(), or executing the callback.
plugin modules register listeners to the application events and modify it
Benefits:
lightweight
rely on npm for dependencies
don't reivent the wheel
Create a plugin prototype for the base
functionality, and let the user define its plugin in a module. In the
module the user would inherit an object from the prototype, extend its
functionality, and then export a constructor which returns the plugin
object.
The main system loads all plugins by require("pluginname") and for
each calls the constructor.