Hello World

A sample go program is show here.

package main

import "fmt"

func main() {
  message := greetMe("world")
  fmt.Println(message)
}

func greetMe(name string) string {
  return "Hello, " + name + "!"
}

Run the program as below:

$ go run hello.go

This is the normal shape of a tiny Go program: main runs first, and fmt.Println writes output.

Variables

Normal Declaration:

var msg string
msg = "Hello"

Shortcut:

msg := "Hello"

This shows both var and the short := form. The short form is the one you will use most inside functions.

Constants
const Phi = 1.618

Use constants for values that should not change, such as fixed ratios, limits, or labels.

Strings
str := "Hello"

Multiline string

str := `Multiline
string`

This shows regular strings and raw multiline strings. Raw strings are handy when you want to keep formatting as written.

Numbers

Typical types

num := 3          // int
num := 3.         // float64
num := 3 + 4i     // complex128
num := byte('a')  // byte (alias for uint8)

Other Types

var u uint = 7        // uint (unsigned)
var p float32 = 22.7  // 32-bit float

Go keeps numeric types explicit. The examples show the common defaults plus a few typed variants when precision or size matters.

Arrays
// var numbers [5]int
numbers := [...]int{0, 0, 0, 0, 0}

This creates a fixed-size array. In day-to-day Go, slices are more common, but arrays are the underlying fixed-length value.

Pointers
func main () {
  b := *getPointer()
  fmt.Println("Value is", b)
func getPointer () (myPointer *int) {
  a := 234
  return &a
a := new(int)
*a = 234

Pointers point to a memory location of a variable. Go is fully garbage-collected.

Pointers let you work with the same value across functions without copying it. Go keeps them simpler than C by handling memory cleanup for you.

Type Conversion
i := 2
f := float64(i)
u := uint(i)

Go does not do many implicit numeric conversions, so converting types directly like this is normal.

Slice
slice := []int{2, 3, 4}
slice := []byte("Hello")

Slices are the main sequence type in Go. They are lightweight views over array-backed data and are used much more than arrays.

Condition
if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}
if _, err := doThing(); err != nil {
  fmt.Println("Uh oh")

This shows the normal if and else if flow in Go, plus the common if err != nil pattern for error handling.

Switch
switch day {
  case "sunday":
    // cases don't "fall through" by default!
    fallthrough

  case "saturday":
    rest()

  default:
    work()
}

Go switch blocks are clean by default because cases do not fall through unless you ask for it explicitly.

Loop
for count := 0; count <= 10; count++ {
  fmt.Println("My counter is at", count)
}
entry := []string{"Jack","John","Jones"}
for i, val := range entry {
  fmt.Printf("At position %d, the character %s is present\n", i, val)
n := 0
x := 42
for n != x {
  n := guess()
}

Go uses for for every looping style: counted loops, range loops, and condition-based loops.

Condition
if day == "sunday" || day == "saturday" {
  rest()
} else if day == "monday" && isTired() {
  groan()
} else {
  work()
}
if _, err := doThing(); err != nil {
  fmt.Println("Uh oh")

Despite the title here, this example is another Go conditional. It shows the same straight-line branching style used in most Go code.

Go Add
func add(param1, param2 int) int {
	return param1 + param2
}

This just adds the two input numbers with the language’s normal arithmetic and returns the sum.

Go Add Border
func addBorder(picture []string) []string {
	border := strings.Repeat("*", len(picture[0]))

	result := make([]string, 0, len(picture)+2)
	result = append(result, border)
	for _, line := range picture {
		result = append(result, "*"+line+"*")
	}
	result = append(result, border)

	return result
}

This builds a new grid with a * border around every side. It adds a full top and bottom row, then wraps each existing row from left and right.

Go Adjacent Elements Product
func adjacentElementsProduct(inputArray []int) int {
	max := inputArray[0] * inputArray[1]

	for i := 0; i < len(inputArray)-1; i++ {
		if p := inputArray[i] * inputArray[i+1]; p > max {
			max = p
		}
	}

	return max
}

This walks through neighboring values, multiplies each pair, and keeps the biggest product it finds.

Go Almost Magic Square
func almostMagicSquare(a []int) []int {
	var grid [3][3]int
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			grid[i][j] = a[i*3+j]
		}
	}

	rowSum := make([]int, 3)
	colSum := make([]int, 3)
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			rowSum[i] += grid[i][j]
			colSum[i] += grid[j][i]
		}
	}

	maxSum := 0
	for k, v := range rowSum {
		maxSum = max(maxSum, v, colSum[k])
	}

	for i, j := 0, 0; i < 3 && j < 3; {
		diff := min(maxSum-rowSum[i], maxSum-colSum[j])
		grid[i][j] += diff
		rowSum[i] += diff
		colSum[j] += diff

		if rowSum[i] == maxSum {
			i++
		}
		if colSum[j] == maxSum {
			j++
		}
	}

	result := make([]int, 0, 9)
	for i := 0; i < 3; i++ {
		for j := 0; j < 3; j++ {
			result = append(result, grid[i][j])
		}
	}

	return result
}

This adjusts the matrix toward a matching target sum so the rows and columns line up more like a magic square.

Go Are Equally Strong
func areEquallyStrong(yourLeft, yourRight, friendsLeft, friendsRight int) bool {
	return max(yourRight, yourLeft) == max(friendsLeft, friendsRight) &&
		min(yourLeft, yourRight) == min(friendsRight, friendsLeft)
}

This compares each person’s strongest and weakest arm. If both pairs match, the result is true.

Go Array Change
func arrayChange(a []int) int {
	moves := 0

	for k := 0; k < len(a)-1; k++ {
		if a[k] >= a[k+1] {
			diff := a[k] - a[k+1] + 1
			a[k+1] += diff
			moves += diff
		}
	}

	return moves
}

This moves left to right and bumps values only when needed so the array becomes strictly increasing.