BASEDIR = $(shell pwd)
APPNAME = $(shell basename $(BASEDIR))

PACKAGE = github.com/<username>/$(APPNAME)

SOURCE_FILES?=./...
TEST_PATTERN?=.
TEST_OPTIONS?=-v

export GO111MODULE := on

LINTERS = fmtcheck lint tidy

.DEFAULT_GOAL := help

.PHONY: clean tools build build test fmt fmtcheck lint cover clean tidy

tools: ## setup
	curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.37.1

# Uncomment this rule for building executable
#build: $(LINTERS) ## build
#	GOOS=linux GOARCH=amd64 go build -v -o $(GOPATH)/bin/$(APPNAME)-linux-amd64 $(PACKAGE)
#	GOOS=darwin GOARCH=amd64 go build -v -o $(GOPATH)/bin/$(APPNAME)-darwin-amd64 $(PACKAGE)
#	GOOS=windows GOARCH=amd64 go build -v -o $(GOPATH)/bin/$(APPNAME)-windows-amd64.exe $(PACKAGE)

# Uncomment this rule for building library
#build: $(LINTERS) ## build
#	go build ./...

# If building a library, test should depend on build-lib
test: $(LINTERS) ## test
	go test $(TEST_OPTIONS) -failfast -race -coverpkg=./... -covermode=atomic -coverprofile=coverage.txt $(SOURCE_FILES) -run $(TEST_PATTERN) -timeout=2m

fmt: ## format
	@echo "==> Fixing source code with gofmt..."
	gofmt -s -w ./$(PKG_NAME)

fmtcheck: ## check format
	@sh -c "'$(CURDIR)/gofmtcheck.sh'"

lint: ## lint
	@echo "==> Checking source code against linters..."
	@GOGC=30 golangci-lint run ./...

tidy: ## tidy
	go mod tidy

cover: test ## generate coverage report
	go tool cover -html=coverage.txt

clean: ## clean
	rm $(GOPATH)/bin/$(APPNAME)*
	
run: build ## run
	$(GOPATH)/bin/$(APPNAME)-linux-amd64 $(filter-out $@,$(MAKECMDGOALS))
%:
	@:

help: ## help
	@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'

The Makefile has a dependency on gofmtcheck.sh script listed below


#!/usr/bin/env bash

# Check gofmt
echo "==> Checking that code complies with gofmt requirements..."
gofmt_files=$(find . -name '*.go' | grep -v vendor | xargs gofmt -l -s)
if [[ -n ${gofmt_files} ]]; then
    echo 'gofmt needs running on the following files:'
    echo "${gofmt_files}"
    echo "You can use the command: \`make fmt\` to reformat code."
    exit 1
fi

exit 0

.gitignore for Go projects


# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Dependency directories (remove the comment below to include it)
# vendor/

A docker file for go applications


FROM golang:1.15

ARG app_env
ENV APP_ENV $app_env

COPY ./path/to/app /go/src/github.com/<username>/<app>
WORKDIR /go/src/github.com/<username>/<app>

RUN make tools
RUN make build

CMD if [ ${APP_ENV} = production ]; \
	then \
	/go/bin/<app>-linux-amd64; \
	else \
	go get github.com/pilu/fresh && \
	fresh; \
	fi

EXPOSE 8090

To build the docker image for dev, use


docker build -f /path/to/dockerfile -t <tag> ./

To build for production, use


docker build -f /path/to/dockerfile -t <tag> ./ --build-arg app_env=production