Getting Started With Golang
Getting started with golang#
Go has a rigid type system and greater performance (as it is compiled)
You can use go
to build websites but the author prefers ruby and go.
There are no dependencies when running a compiled go
program.
A good tool for command line interface programs.
Installing#
No Install playground: Go Dev Playground
Install precompiled binaries Go DL
Go is designed to work when your code is inside a workspace.
The workspace is a folder composed of bin
, pkg
and src
subfolders.
You might be tempted to force Go to follow your own style - don’t.
Compiling#
-
Download the archive
wget go1.18.darwin-amd64.tar.gz
-
Set up environment variables
echo ‘export GOPATH=$HOME/code/go’ >> $HOME/.profile echo ‘export PATH=$PATH:/usr/local/go/bin’ >> $HOME/.profile
-
Check your go version
go version go version go1.18 darwin/amd64
1. The Basics#
It is a:
- compiled - convert source code into lower level machine code
- statically-typed language - variables must be defined as a specific type (the compiled can infer the type) - python is dynamically typed
- C-like syntax
Go’s goal is to ensure fast compile times
Compiled languages tend to run faster and the executable can be run without additional dependencies (at least, that’s true for languages like C, C++ and Go which compile directly to assembly).
Semi-colon and parenthesis around conditions are removed:
if name == "Leto" {
print("the spice must flow")
}
Parenthesis are still used in complicated cases:
if (name == "Goku" && power > 9000) || (name == "gohan" && power < 4000) {
print("super Saiyan")
}
Go has garbage collection:
Languages with garbage collectors (e.g., Ruby, Python, Java, JavaScript, C#, Go) are able to keep track of these and free them when they’re no longer used.
In main.go
:
package main
func main() {
println("it's over 9000!")
}
Compile with:
go run main.go
A temporary directory is created
go run --work main.go
To just build the code:
go build main.go
Then you can run it with:
./main.go
Main#
In Go, the entry point to a program has to be a function called main within a package main.
Compiling without a main()
function might work and is common when developing a library - there is just no entrypoint to run it.
Imports#
Go has a few built-ins like println
We can’t go far without making use of go’s standard library.
The import
keyword is used to declare packages used by the file.
package main
import (
"fmt"
"os"
)
func main() {
if len(os.Args) != 2 {
os.Exit(1)
}
fmt.Println("It's over", os.Args[1])
}
Run:
go run import.go
We are using fmt
and os
.
The argument at index 0 - is always the currently running executable
The go library is well documented eg. fmt
Go Docs#
Get the docs locally without internet:
godoc -http=:6060
I had to install it with:
go install golang.org/x/tools/cmd/godoc@latest
- it still did not work
Variables and Declarations#
Basic declaration is:
var NAME TYPE
eg.
var power int = 9000
or:
func main() {
power := getPower()
}
func getPower() int {
return 9001
}
or:
name, power := "Goku", 9000
or:
var power int
power = 9000
Go will not compile if you have unused variables
Function Declarations#
One with no return value:
func log(message string) {
}
One with one return value:
func add(a int, b int) int {
}
One with 2 return values:
func power(name string) (int, bool) {
}
Which is used like:
value, exists := power("goku")
if exists == false {
// handle this error case
}
If you only care about the first value:
_, exists := power("goku")
if exists == false {
// handle this error case
}
If parameters share the same type you can use this syntax:
func add(a, b int) int {
}
Inferred types and multiple return values - are a similarity with dynamically typed languages.
2. Structures#
It is not Object oriented. It does not have objects or inheritance. It doesn’t have polymorphism or overloading.
Go does have structures.
Composition over inheritance
type Saiyan struct {
Name string
Power int
}
Declarations and Initialisations#
goku := Saiyan{
Name: "Goku",
Power: 9000,
}
The trailing
,
is required
You don’t have to set everything:
goku := Saiyan{}
or
goku := Saiyan{Name: "Goku"}
goku.Power = 9000
or
goku := Saiyan{"Goku", 9000}
Go passes arguments to functions as copies
func main() {
goku := Saiyan{"Goku", 9000}
Super(goku)
fmt.Println(goku.Power)
}
func Super(s Saiyan) {
s.Power += 10000
}
So the answer above would be 9000
To pass the pointer:
func main() {
goku := &Saiyan{"Goku", 9000}
Super(goku)
fmt.Println(goku.Power)
}
func Super(s *Saiyan) {
s.Power += 10000
}
- The
&
operator gets the address of the value - The type
*Saiyan
means the pointer to theSaiyan
- We still pass a copy but the copy is of the same address
- Copying a pointer is cheaper than the whole data structure
- Ruby, Python, Java and C# behave this way
- On a 64-bit machine, a pointer is 64 bits large.