Go Language Cheatsheet
Hello world 🔗
- create a new directory with a name like
hellogo
. - create a new file inside with the name
main.go
. - add this code inside that
main.go
file.
package main
import "fmt"
func main() {
message := greetMe("world")
fmt.Println(message)
}
func greetMe(name string) string {
return "Hello, " + name + "!"
}
- open the directory in a Terminal, and run
go mod init hellogo
- then
go mod tidy
- then build the project with
go build main.go
- run the program with
./main
, you’ll seeHello world
as a result of program execution.
Constants in Go 🔗
Constants can be character, string, boolean, or numeric values.
const Phi = 1.618
const Size int64 = 1024
const x, y = 1, 2
const (
Pi = 3.14
E = 2.718
)
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
Variables in Go 🔗
- Variable declaration
var msg string
var msg = "Hello, world!"
var msg string = "Hello, world!"
var x, y int
var x, y int = 1, 2
var x, msg = 1, "Hello, world!"
msg = "Hello"
- Declaration list
var (
x int
y = 20
z int = 30
d, e = 40, "Hello"
f, g string
)
Go can infer the variable type, so you can just write this.
msg := "Hello"
x, msg := 1, "Hello"
Basic types of Go language 🔗
Strings:
str := "Hello"
str := `Multiline
string`
Numbers:
num := 3 // int
num := 3. // float64
num := 3 + 4i // complex128
num := byte('a') // byte (alias for uint8)
var u uint = 7 // uint (unsigned)
var p float32 = 22.7 // 32-bit float
Type conversions:
i := 2
f := float64(i)
u := uint(i)
Arrays: Arrays have a fixed size.
// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}
Slices: Slices have a dynamic size, unlike arrays.
slice := []int{2, 3, 4}
slice := []byte("Hello")
Pointers:
Pointers point to a memory location of a variable. Go is fully garbage-collected.
func main () {
b := *getPointer()
fmt.Println("Value is", b)
}
func getPointer () (myPointer *int) {
a := 234
return &a
}
a := new(int)
*a = 234
Flow control 🔗
Conditional:
if day == "sunday" || day == "saturday" {
rest()
} else if day == "monday" && isTired() {
groan()
} else {
work()
}
Statements in if:
A condition in an if statement can be preceded with a statement before a ;. Variables declared by the statement are only in scope until the end of the if.
if _, err := doThing(); err != nil {
fmt.Println("Uh oh")
}
For loop:
for count := 0; count <= 10; count++ {
fmt.Println("My counter is at", count)
}
For-Range loop:
entry := []string{"Abanoub","Hanna","Bob"}
for i, val := range entry {
fmt.Printf("At position %d, the character %s is present\n", i, val)
}
Switch:
switch day {
case "sunday":
// cases don't "fall through" by default!
fallthrough
case "saturday":
rest()
default:
work()
}
While loop:
n := 0
x := 42
for n != x {
n := guess()
}
Functions in Go 🔗
Lambdas:
myfunc := func() bool {
return x > 10000
}
Multiple return types:
a, b := getMessage()
func getMessage() (a string, b string) {
return "Hello", "World"
}
Named return values:
By defining the return value names in the signature, a return (no args) will return variables with those names.
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return
}
Packages in Go 🔗
Importing:
import "fmt"
import "math/rand"
Or
import (
"fmt" // gives fmt.Println
"math/rand" // gives rand.Intn
)
Both are the same.
Aliases:
import r "math/rand"
r.Intn()
Packages:
Every package file has to start with package.
package hello
Exporting names:
Exported names begin with capital letters.
func Hello () {
···
}
Concurrency in Go 🔗
Goroutines:
Channels are concurrency-safe communication objects, used in goroutines.
func main() {
// A "channel"
ch := make(chan string)
// Start concurrent routines
go push("Moe", ch)
go push("Larry", ch)
go push("Curly", ch)
// Read 3 results
// (Since our goroutines are concurrent,
// the order isn't guaranteed!)
fmt.Println(<-ch, <-ch, <-ch)
}
func push(name string, ch chan string) {
msg := "Hey, " + name
ch <- msg
}
Buffered channels:
Buffered channels limit the amount of messages it can keep.
ch := make(chan int, 2)
ch <- 1
ch <- 2
ch <- 3
// fatal error:
// all goroutines are asleep - deadlock!
WaitGroup:
A WaitGroup waits for a collection of goroutines to finish. The main goroutine calls Add to set the number of goroutines to wait for. The goroutine calls wg.Done() when it finishes.
import "sync"
func main() {
var wg sync.WaitGroup
for _, item := range itemList {
// Increment WaitGroup Counter
wg.Add(1)
go doOperation(&wg, item)
}
// Wait for goroutines to finish
wg.Wait()
}
func doOperation(wg *sync.WaitGroup, item string) {
defer wg.Done()
// do operation on item
// ...
}
Closing channels:
// Closes a channel
ch <- 1
ch <- 2
ch <- 3
close(ch)
// Iterates across a channel until its closed
for i := range ch {
···
}
// Closed if ok == false
v, ok := <- ch
Error control 🔗
Defer:
Defers running a function until the surrounding function returns. The arguments are evaluated immediately, but the function call is not ran until later.
func main() {
defer fmt.Println("Done")
fmt.Println("Working...")
}
Deferring functions:
The defer func uses current value of d, unless we use a pointer to get final value at end of main.
func main() {
defer func() {
fmt.Println("Done")
}()
fmt.Println("Working...")
}
Lambdas are better suited for defer blocks.
func main() {
var d = int64(0)
defer func(d *int64) {
fmt.Printf("& %v Unix Sec\n", *d)
}(&d)
fmt.Print("Done ")
d = time.Now().Unix()
}
Structs 🔗
Defining:
type Vertex struct {
X int
Y int
}
func main() {
v := Vertex{1, 2}
v.X = 4
fmt.Println(v.X, v.Y)
}
Literals: You can also put field names.
v := Vertex{X: 1, Y: 2}
// Field names can be omitted
v := Vertex{1, 2}
// Y is implicit
v := Vertex{X: 1}
Pointers to structs:
Doing v.X
is the same as doing (*v).X
, when v
is a pointer.
v := &Vertex{1, 2}
v.X = 2
Methods 🔗
Receivers:
There are no classes, but you can define functions with receivers.
type Vertex struct {
X, Y float64
}
func (v Vertex) Abs() float64 {
return math.Sqrt(v.X * v.X + v.Y * v.Y)
}
v := Vertex{1, 2}
v.Abs()
Mutation:
By defining your receiver as a pointer (*Vertex), you can do mutations.
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
v := Vertex{6, 12}
v.Scale(0.5)
// `v` is updated
Interfaces in Go 🔗
A basic interface:
type Shape interface {
Area() float64
Perimeter() float64
}
Methods:
The methods defined in Shape are implemented in Rectangle.
func (r Rectangle) Area() float64 {
return r.Length * r.Width
}
func (r Rectangle) Perimeter() float64 {
return 2 * (r.Length + r.Width)
}
Struct:
Struct Rectangle implicitly implements interface Shape by implementing all of its methods.
type Rectangle struct {
Length, Width float64
}
Interface example:
func main() {
var r Shape = Rectangle{Length: 3, Width: 4}
fmt.Printf("Type of r: %T, Area: %v, Perimeter: %v.", r, r.Area(), r.Perimeter())
}
More resources to learn Go programming language 🔗
- 7 Reasons You Should Try Go
- Go: functions, methods, pointers and interfaces
- The Only Introduction to Go (Golang) You Need
- Interactive Go Programming With Jupyter
- Plain Socket Communication Between Two Go Programs, the Easy Way
- Create and Run Go service in Docker
- A Tour of Go
- Go Wiki
- Go by Example
- Awesome Go
- Code Optimization Tips With Examples
I hope this post helps you. If you know a person who can benefit from this information, send them a link of this post. If you want to get notified about new posts, follow me on YouTube , Twitter (x) , LinkedIn , and GitHub .