Continuing with my "discussion" and following the guide that I started in my last post I would like to introduce my own personal choice for structuring go projects.
So what's the long term goal:
- Build Client / Server applications.
- Has to be web based.
- Has implement Security standards
- Has to be cross platform (lets cover non mobile OS for now)
- Keeping it as simple as possible...
Follow this Github repository to keep track of this project.
So... let's get started.
[ CODE PART STARTS HERE ]
My development environment:
- Ubuntu 19.04.
- go1.13.1 linux/amd64
For me getting used to GoLang GOPATH (later versions) was complicated, as an old Python developer, projects were all encapsulated in virtualenv and other horrors. ( Don't get me wrong, I love virtualenv)
But I must admit that getting the order that GoLang required from the start boosted my productivity, solve a few issues, and reduce for sure many headaches.
So my environment will start always here:
/home/{user}/projects/src/
Clone my repo
➜ git clone git@github.com:jpramirez/go-web-starterpack.git Cloning into 'go-web-starterpack'... remote: Enumerating objects: 4, done. remote: Counting objects: 100% (4/4), done. remote: Compressing objects: 100% (4/4), done. remote: Total 4 (delta 0), reused 4 (delta 0), pack-reused 0 Receiving objects: 100% (4/4), done. ➜ cd go-web-starterpack ➜ go-web-starterpack git:(MakefileInit) ls -ltrh total 4,0K -rw-r--r-- 1 shellcheff shellcheff 2,4K nov 8 12:30 Makefile ➜ go-web-starterpack git:(MakefileInit)
I was never a fan of C, C++, Makefile, deps and all that, made my brain hurt just by thinking about it, so many dependencies, so many variables, files, libraries... Why someone will create such a horror!!...
Now.. to be honest the best way to start working with Go for me was a makefile.
Easy, plain, no BS, is somehow pretty standard to any Linux environment.
Lets check that file then
TIME=$(shell date +"%Y%m%d.%H%M%S") VERSION=0.1.1-alpha-0.8 BINARY_NAME=go-webstarter-go.v1 BINARY_NAME_SERVER=go-webstarter-server.v1 BASE_FOLDER = $(shell pwd) BUILD_FOLDER = $(shell pwd)/build FLAGS_LINUX = CGO_LDFLAGS="-L./LIB -Wl,-rpath -Wl,\$ORIGIN/LIB" CGO_ENABLED=1 GOOS=linux GOARCH=amd64 FLAGS_DARWIN = OSXCROSS_NO_INCLUDE_PATH_WARNINGS=1 MACOSX_DEPLOYMENT_TARGET=10.6 CC=o64-clang CXX=o64-clang++ CGO_ENABLED=0 FLAGS_FREEBSD = GOOS=freebsd GOARCH=amd64 CGO_ENABLED=1 FLAGS_WINDOWS = GOOS=windows GOARCH=amd64 CC=i686-w64-mingw32-gcc CGO_ENABLED=1 GOFLAGS_WINDOWS = -ldflags -H=windowsgui init: @mkdir -vp $(BASE_FOLDER)/assets @mkdir -vp $(BASE_FOLDER)/build @mkdir -vp $(BASE_FOLDER)/cmd @mkdir -vp $(BASE_FOLDER)/config @mkdir -vp $(BASE_FOLDER)/extras @mkdir -vp $(BASE_FOLDER)/pkg/constants @mkdir -vp $(BASE_FOLDER)/web @mkdir -vp $(BASE_FOLDER)/third-party @mkdir -vp $(BASE_FOLDER)/api @mkdir -vp $(BASE_FOLDER)/vendor @echo "Creating Base Files" @touch $(BASE_FOLDER)/pkg/constants/version.go @touch $(BASE_FOLDER)/vendor/packages_windows.txt @touch $(BASE_FOLDER)/vendor/packages_linux.txt @echo "# README BASE " >> $(BASE_FOLDER)/Readme.md check-env: @mkdir -p $(BUILD_FOLDER)/dist/linux/bin @mkdir -p $(BUILD_FOLDER)/dist/windows/bin @mkdir -p $(BUILD_FOLDER)/dist/arm/bin @mkdir -p $(BUILD_FOLDER)/dist/osx/bin cp -R config $(BUILD_FOLDER)/dist/linux/ cp -R config $(BUILD_FOLDER)/dist/windows/ cp -R config $(BUILD_FOLDER)/dist/arm/ cp -R config $(BUILD_FOLDER)/dist/osx/ cp -R extras $(BUILD_FOLDER)/dist/linux/ cp -R assets $(BUILD_FOLDER)/dist/linux/ ## Linting lint: @echo "[lint] Running linter on codebase" @golint ./... getdeps: ./getDeps.sh versioning: ./version.sh ${VERSION} ${TIME} build/weblayer-linux: cd cmd/WebServer && ${FLAGS_LINUX} go build -o ${BUILD_FOLDER}/dist/linux/bin/${BINARY_NAME_SERVER} . run/dev: cd build/dist/linux && bin/${BINARY_NAME_SERVER} --config config/config.json build/dev: check-env build/weblayer-linux run/dev clean: rm -Rvf build/dist/ startover: @rm -fr $(BASE_FOLDER)/assets @rm -fr $(BASE_FOLDER)/build @rm -fr $(BASE_FOLDER)/cmd @rm -fr $(BASE_FOLDER)/config @rm -fr $(BASE_FOLDER)/extras @rm -fr $(BASE_FOLDER)/pkg @rm -fr $(BASE_FOLDER)/web @rm -fr $(BASE_FOLDER)/third-party @rm -fr $(BASE_FOLDER)/api @rm -fr $(BASE_FOLDER)/vendor @rm $(BASE_FOLDER)/Readme.md
So a few take away are:
One makefile is all you need to jump start your project, will create the appropriate folders, README and directory structur.
➜ go-web-starterpack git:(MakefileInit) make init mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/assets' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/build' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/cmd' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/config' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/extras' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/pkg' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/pkg/constants' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/web' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/third-party' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/api' mkdir: created directory '/home/shellcheff/projects/src/github.com/epyphite/go-web-starterpack/vendor' Creating Base Files ➜ go-web-starterpack git:(MakefileInit) ✗ ls -ltrh total 48K -rw-r--r-- 1 shellcheff shellcheff 2,4K nov 8 12:30 Makefile drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 build drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 assets drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 extras drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 config drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 cmd drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 web drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 third-party drwxr-xr-x 3 shellcheff shellcheff 4,0K nov 8 12:45 pkg drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 api drwxr-xr-x 2 shellcheff shellcheff 4,0K nov 8 12:45 vendor -rw-r--r-- 1 shellcheff shellcheff 15 nov 8 12:45 Readme.md ➜ go-web-starterpack git:(MakefileInit) ✗
As you notice we created a few folders and a few files, lets try to explain a little bit.
- build
This folder will be use as output of any compilation and building, we can then divide it into distributions, operating systems and flavor ( we get to that later )
- assets
In this case assets will hold anything http/web related. Such as css, images, js, vue.js and templates.
- extras
Anything "extra", such as tls and ssl certificates, tool configurations, or things needed to run. In our particular project this will be TLS certificates.
- config
Configuration file in json for our app. We will get to this later, but lets just say it easy to have a config/config.json available.
- cmd
From go standard "Main applications for this project." that means minimal code to run our application.
- web
Here I will put all the code related to a webserver implementation, and any webapp. Usually I like to divide webserver.go with webapp.go. But we will get to that later.
- third-party
Reserved for any plugin, auxiliary library, or later in this series protobuf libraries.
- pkg
THE MAIN LIBS goes here, all the code for our app, implementations, classes, storage drivers etc...
- api
Will hold any specifications, like swagger or protobuf (later)
- vendor
Coming from python I rather prefer to have my package.txt file. Don't get me wrong vendoring in Go is mature, I just... don't like it enough. And so far for me has been easier and simpler to get a vendor folder with a few txt files listing my dependencies.
Again, this is my preferred way to order my code and projects, makes it easier for me to handle and specially to spin projects fast.
In my next posts I will show you how to use this structure to easily spin a web server, create a configuration files, build and package it :)
[ CODE PART ENDS HERE ]
[ RANT PART STARTS HERE ]
Today is Friday... So will not be a rant directly associated with this post...
I wish you all happy coding, and PM me for comments or fixes :)
Top comments (0)