- Installing Go
- Commonly Used Go Commands
- Hello World
go fmt
go vet
- Go Dev Tools
- Go Compatibility Promise
- Staying Up-To-Date
- Every programming language needs a development environment
- We will setup a development environment for Go
- We only need to install Go: No additional tools
- Check here for installation instructions
- Check here for all available releases
- Go programs compile to a single native binary
- Standalone: No VM needed to run the compiled applications
- No additional software required to run
- Go apps can also be packaged inside Docker images
- Download latest
.tar.gz
file from official website into your Downloads directory
cd ~/Downloads
wget https://go.dev/dl/{{go_version}}.tar.gz
- Remove any previous installation, if any
- Extract the new archive into installation location
sudo rm -rf /usr/local/go
tar -C /usr/local -xzf {{go-version}}.tar.gz
- Add
/usr/local/go/bin
to thePATH
environment variable
export PATH=$PATH:/usr/local/go/bin
source $HOME/.bash_profile
- Verify the installation
go version
which go
sudo rm -rf /usr/local/go
sudo rm /etc/paths.d/go
- Remove the Go paths from these files, if any
/etc/profile
$HOME/.bash_profile
$HOME/.profile
$HOME/.bashrc
- Download latest
.msi
file from official website into Downloads directory - Open the
.msi
file and follow installation prompts - Close and reopen any open command prompts or shell prompts
- Verify the installation
go version
where go
- Remove from Control Panel
- Or remove with
msiexec
via the.msi
installation file
msiexec /x go{{version}}.windows-{{cpu_arch}}.msi /q
- Download latest
.pkg
file from official website into Downloads directory - Open the
.pkg
file and follow installation prompts - Close and reopen any open command prompts or shell prompts
- Verify the installation
go version
which go
sudo rm -rf /usr/local/go
sudo rm /etc/paths.d/go
- Remove the Go paths from these files, if any
/etc/profile
$HOME/.bash_profile
$HOME/.profile
$HOME/.bashrc
Command | Action |
---|---|
go version |
Check installed Go version |
go build |
Compiles multiple Go source code files into executable binaries |
go run |
Compiles and executes multiple Go source code files (build & execute) But does not produce an actual executable |
go fmt |
When ran in a directory with .go files, formats all the code in each file in the directory |
go vet |
When ran in a directory with .go files, scans for common coding mistakes |
go install |
Compiles and installs a package and dependencies |
go get |
Download raw source code of someone else's package as dependency |
go test |
Runs any tests associated with the current projects |
go mod |
For dependency management and module management |
go mod tidy |
Verify existing module dependencies Adds missing and removes unused modules |
go bug |
Start a bug report |
go clean |
Remove object files and cached files |
go doc |
Show documentation for package or symbol |
go env |
Print Go environment information |
go fix |
Update packages to use new APIs |
go generate |
Generate Go files by processing source |
go list |
List packages or modules |
go work |
Workspace maintenance |
go tool |
Run specified go tool |
- You are free to organize your project as you see fit
- Here is a suggested project structure
Go-Module/
├── bin/
| ├── debug/
| └── release/
├── src/
| └── main.go
├── tests/
├── go.mod
├── makefile
└── readme.md
- A Go project is called a Go Module
- A Go Module is a directory with a
go.mod
file in it go.mod
can be auto-generated with the following command in the module directory
- A Go Module is a directory with a
go mod init unique/module/path/typically/github
- A
go.mod
file declares:- The name of the module and its unique path
- Minimum supported Go version
- Any additional module dependencies
- The
go.mod
file should not be edited directly- Use
go
command to manage its contents go mod
creates itgo get
adds dependenciesgo mod tidy
verifies dependencies
- Use
- The module is then defined in
go.mod
file as follow
module unique/module/path/typically/github
go 1.23.2
- Define executable code in
main.go
package main
import "fmt"
// This is the main entry of the application.
func main() {
fmt.Println("Hello World!")
}
- Within a Go Module, codes are organized into one or more packages
main
package contains executable code- Any other package names are reusable libraries
- A package is essentially a directory (except for
main
)
- Allows to import external packages referenced in the file
- Go
import
only imports whole packages - We cannot limit the imports to specific functions or atomic elements
- Go
fmt
is from the standard library so it is already available- No need to use
go get
- For 3rd-Party libraries, we use
go get
first
- No need to use
- All executable Go programs start execution from the
main()
function in themain
package
Command | Action |
---|---|
go build |
Compiles multiple Go source code files into executable binaries |
go run |
Compiles and executes multiple Go source code files (build & execute) But does not produce an actual executable |
- To run
go run Go-Module-Name/src/main.go
- To build/compile into binaries
go build -o Go-Module-Name/bin/Hello-World Go-Module-Name/src/main.go
- To run after compile
./Go-Module-Name/bin/Hello-World
- To build/compile into binaries AND run
go build -o Go-Module-Name/bin/Hello-World Go-Module-Name/src/main.go && ./Go-Module-Name/bin/Hello-World
- NOTE: By default,
go build
uses the name of the module as the name of the binary output- To specify a new name or path, we use the
-o
flag
- To specify a new name or path, we use the
- Go allows to write code efficiently
- Simple syntax and fast compile
- Go also has an enforced standard code-formatting
- This simplifies the compiler
- Makes easier collaborations
- More productive
- Avoid unnecessary arguments over styles and formatting
- E.g. It is a syntax error if the opening brace is not on the same line as the declaration or block command
- Also allows some clever tools to generate code
go fmt
command can be run on all files in the project- Only run this from within a module directory
# Fix formatting everywhere
go fmt ./...
- NOTE: Remember to always run
go fmt
before compiling/building and pushing to version control- This is one of the first step to ensure quality code
- It is a good practice to make a separate commit that only does
go fmt ./...
- Helps to avoid combining logic changes and formatting changes
- NOTE: In VS Code, it is possible to activate auto-formatting by
gofmt
via the Go extension settings
- Go normally requires
;
at the end of every statement - However, Go developers should never put those
;
manually - The Go compiler inserts them automatically by following a rule
- The short insertion rule is: If the newline comes after a token that could end a statement, insert a semicolon
- That is, a semicolon is inserted at the newline if the last token before the newline is either:
- An identifier,
- A basic literal,
- Or any of
break
,continue
,fallthrough
,return
,--
,++
,)
,}
- That is, a semicolon is inserted at the newline if the last token before the newline is either:
- Because of this rule, braces must be placed strategically
- Following the correct code-formatting is required
- Automatic Semicolon Insertion rule results in
- Go compiler running simpler and faster
- Enforced coding-style standard
// The following breaks because...
func main() // ...a semicolon is automatically added here
{
fmt.Println("This breaks!")
}
// However, the following works because..
func main() { // ...no automatic semicolon insertion here
fmt.Println("This works!")
}
- It is possible for code to be syntactically valid yet likely incorrect
go vet
can detect some of these errors- Run it in a directory with
.go
files to scan for common coding mistakes
package main
import "fmt"
// This is the main entry of the application.
func main() {
fmt.Printf("Hello %s!\n")
}
- Running
go vet
on the above code capture the error- No value was specified for the placeholder of
Printf()
- The code will still compile and run
- However, it is not correct
- No value was specified for the placeholder of
- NOTE: Always run
go vet
before compiling/building and pushing to version control- This is one of the first step to ensure quality code
- NOTE: In VS Code, it is possible to activate Vet On Save with
go vet
via the Go extension settings - NOTE:
fmt.Printf()
allows Print Formattingfmt.Sprintf()
allows String Interpolation
package main
import "fmt"
// This is the main entry of the application.
func main() {
fmt.Printf("Hello %s!\n", "world")
}
- NOTE:
go vet
can capture many bugs, but it cannot capture all bugs- We can use additional 3rd-party quality-code tools
- Follow additional advices from Effective Go and Go Wiki: Go Code Review Comments
- A simple Text Editor and Go commands can be used to write small programs
- However, better IDEs or Advanced Editors are necessary for larger projects
- Auto-format on save (
go fmt
) - Auto-error-checking (
go vet
) - Code completion
- Type checking
- Code navigation
- Integrated debugging
- Auto-format on save (
- There are multiple options for Go IDEs and Advanced Editors
- Here, we are using VS Code + Go Extension
- Download VS Code
- Open any
.go
file with VS Code for the first time- The Go-related extensions will automatically install
- If not, search the
Go
extension and install
- The installation includes all the tools listed here, which includes
- A language server
gopls
- A debugger
dlv
- Unit Test
gotests
- Linter
staticcheck
- A language server
- Tools can be updated via the VS Code Command (CTRL+SHIFT+P)
Go: Install/Update Tools
- An IDE is nice to use but hard to automate
- Automated build is essential
- Requiring this tooling is good software engineering practice
- Use scripts to specify the build steps
- Go developers can use
make
as the principal build solutionmake
has been used to build programs since 1976- Specify a set of operations for building the program
- Specify the order in which to perform the steps
sudo apt-get install build-essential
- To use
make
- Create a
makefile
in the project/module directory - Add the content for building the project
- Create a
- NOTE: Make sure to use tabs for the whitespaces for indentation in a makefile
- NOTE: In VSCode, it is helpful to also install a Makefile-support extensions
- The Makefile Tools by Microsoft is a good extension to have
# NOTE: Make sure all indentations use actual tabs
# DEFAULT_GOAL specifies the default target
# This is run when no target is provided during the call
.DEFAULT_GOAL := try-run
# Target definitions
# .PHONY helps avoid possible name-collisions with other directory or file names on the computer
.PHONY: fmt vet build build-release run run-release try-build-run try-run
# Target
fmt:
# Task: Format all source files
cd src
go fmt ./...
cd ..
# Target
vet: fmt
# Task: Verify any possible errors
cd src
go vet ./...
cd ..
# Target
build: vet
# Task: Build module
go build -o bin/debug/Hello-World src/main.go
# Target
build-release: vet
# Task: Build module for release, strip symbols
go build -ldflags="-s -w" -o bin/release/Hello-World src/main.go
# Target
run: build
# Task: Build module then run
bin/debug/Hello-World
# Target
run-release: build-release
# Task: Build module for release then run
bin/release/Hello-World
# Target
try-build-run: vet
# Task: Build module, run, then remove built binary
if test -f bin/debug/Hello-World-Temp; then \
rm -f bin/debug/Hello-World-Temp; \
fi
go build -o bin/debug/Hello-World-Temp src/main.go
bin/debug/Hello-World-Temp
rm -f bin/debug/Hello-World-Temp
# Target
try-run: vet
# Task: Test-Run the module without building anything
go run src/main.go
- Target
- Each possible operation
DEFAULT_GOAL
specifies the default target- This is run when no target is provided during the call
- Target Definitions
- The word before
:
is the name of the target - After
:
is a requirement target that must run before running the current target
- The word before
.PHONY
helps avoid possible name-collisions with other directory names or file names on the computer
Command | Description |
---|---|
make |
Runs the target specified under DEFAULT_GOAL |
make <target> |
Runs the requirements and steps specific for that target |
- Ensuring that formatting and vetting always happen before building is a great improvement in the build process
- Drawbacks of Makefiles
- They are picky: Must indent with tabs only
- Not supported out-of-the-box on Windows
- Must install
make
first:choco install make
- Must install
- Additional resources for learning Makefiles
- Go is periodically updated
- New release roughly occurs every 6 months
- Patches and security fixes are as-needed
- Releases tend to be incremental than expansive
- The Go team plans to avoid breaking changes by following the Go Compatibility Promise
- For any version with Major 1, there is no expected breaking changes to the language or standard library
- Unless a breaking change is required for bug or security fix
- But this guarantee does not apply to Go commands
- Updating Go environment does not affect previously-compiled programs
- Go compiles to standalone native binary
- There is no dependency on any VMs
- The version of Go does not affect the runtime of compiled programs
System | Option |
---|---|
Windows | chocolatey can be used to install and update Go |
Mac | brew can be used to install and update Go |
Linux | - Move the current installation in a backup location - Download and unpack the new installation - If all is good, delete the backup |
Others | Follow the installer's option for removing and re-installing |