kdocs
GitHub
Lang - Runtime
Lang - Runtime
  • Go
    • Modules & Packages
    • Variables
    • Structs
    • Interfaces
    • Functions
    • Control Structures
    • Erro Handling
    • Concurrency
    • Testing
    • Fuzzing
  • Web
    • V8 Engine
    • Node.js
      • New Project
    • Deno
      • New Project
Powered by GitBook
On this page
  • Variables
  • Single vs Double quotes
  • Basic types
  • Custom types (alias)
  • Check a value type
  • Generic types
  • Fetch user input (Stdin)
  • Formatting strings
  • Multiline strings
  • Variable scopes
  • Unamed variables
  • Constants
  • Pointers
  • Arrays
  • Slices
  • Maps
  1. Go

Variables

Variables

Create variables with var or with :=.

The convention is to declare variables with := and not var.

BUT, you can't explicitly state the variable type. (Ex: a int := 5)

All Go types come with a "null value" (not nil) which is set in a variable if no other value is explicitly set.

For instance:

  • int => 0

  • float64 => 0.0

  • string => ""

  • bool => false

  • pointer => nil

var a = 1000 // Inferred "int"
var b float64 = 5.5
var y = float64(a) + b

c := 1000 // Inferred "int"

Variable types can be inferred from values.

In Go you cannot mix types in calculations.

Declare multiple variables in one line

But they will all be of the same type. (You cannot specifiy the type for each one)

var a, b float64 = 1000, 40.1
a, b := 1000, 40.1

Single vs Double quotes

In Go there is a different when using ' vs ".

Single Quotes

Should be used to designate Rune or Byte values.

Double Quote

Should be used to designate String values.

Basic types

  • int, uint (only positives), int32

  • float64

  • string (Immutable)

  • bool

  • byte (alias for uint8) (Created with single quotes)

  • rune (alias for int32) (Created with single quotes)

Custom types (alias)

Create alias types with type keyword.

// Creates a new type "A" that is "exported" in the package
type A int
var a A = 1

type floatMap map[string]float64
var m floatMap

Add methods to these aliases

Inject methods to these custom type aliases.

type str string

func (text str) log() {}

var a str = "This"
a.log()

Check a value type

You can check if a variable is of a specific type AND get its value on that type.

typeVal, ok := value.(int)

You may also do stuff depending on the variable type.

value.(type) is only available inside this switch.

switch value.(type) {
    case int:
        ...
    case todo:
        ...
    // Optional - for all other types of values
    default:
        ...
}

Generic types

When you have to accept multiple types, but using interface{} is just too wide.

This is kind of like using Typescript generic type to handle type union number | string.

Instead of working with interface{}.

func add(a, b interface{}) interface{} {
    // Check value types and do stuff based on it
}

Use a generic type, and specify which types are valid.

func add[T int | float64 | string](a, b T) T {
    return a + b
}

Multiple generic types

func add[T any, K any](a, b T) K {
   ... 
}

Fetch user input (Stdin)

fmt.Scan

You can't easily fetch multi-word input values.

var a float64

fmt.Print("Enter value: ")
fmt.Scan(&a) // Pass a pointer of the variable

bufio.NewReader(os.Stdin)

To read multiple words

var a string

fmt.Print("Enter text: ")
reader := bufio.NewReader(os.Stdin)
text, err := reader.ReadString('\n') // Pay attention to the Single quotes

text = string.TrimSuffix(text, "\n") // To remove the line break that stopped the buffer
text = string.TrimSuffix(text, "\r") // In Windows a line break usually comes with \r\n

Formatting strings

fmt.Printf("%.2f", a)
var a string = fmt.Sprintf("%.2f", b)

Multiline strings

var a string = `
    This is multi
    line
`

Variable scopes

Variables or constants can be declared outside of main().

In this case a will be accessable/scoped to the entire file main.go.

But you can't declare these variables with :=.

main.go
var a string = 'AAA'

b := 10 // Can't use this type of declaration

func main() {
    ...
}

Unamed variables

You may use _ as variables to handle values that will not be used.

a, _ := name()

Constants

Declare constants with const.

const a = 1000 // Inferred "int"
const b float64 = 5.5

Pointers

Pointers are variables that store memory addresses instead of values.

Use them to directly mutate variables or to avoid memory duplication.

By default Go pass variables by value to functions.

// Inferred type
aPointer := &a
// Explicit type
var aPointer *int = &a

fmt.Print(aPointer) // Shows the memory address of "a"
fmt.Print(*aPointer) // Show the value of "a"

Pass parameter by reference

func name(val *string) string {
    return *val
}

a := 'A'

name(&a)

Arrays

Declared only

Arrays that are only declared:

  • With size: Will be "empty", but they will ocupy 4 * int space in memory.

  • Without size: Will trutly be empty and ocupy no space in memory.

// Without size
var a []int
var a []int = []int{}
a := []int{}

// With size
var a [4]int
var a [4]int = []int{}
a := [4]int{}

Instantiated (Specified size)

If a size is specified than the Array will have that size, no more and no less.

// An array of size 4
var a [4]int = [4]int{1, 2, 3, 4}

a := [4]int{1, 2, 3, 4}

Instantiated (Dynamic size)

If no size was specifed, a Slice is created.

Under the hood, Go also creates an Array with the Slice size.

// An array of size 2
var a []int = []int{1, 2}

a:= []int{1, 2}

Access value of array

Accessing indexes out of range will generate a panic with 'runtime error'.

a[0]

Lenght and Capacity

Lenght gives the number of values in the Slice or Array.

Capacity:

  • In Array is the same as len.

  • In a Slice will be the size of the Array by which the Slice was generated initialy.

a := [5]int{1, 2, 3}
len(a) // 3
cap(a) // 3

b := a[:1]
len(b) // 1
cap(b) // 3

Slices

A subset (start, end] of an Array or other Slices. (Including the start index, and excluding the end index)

Slices are created by REFERENCE. (They are not copies)

  • You can't use negative indexes.

  • You can't provide indexes that are out of range.

// Slice from index "1" [included], to index "3" [excluded]
aSlice := a[1:3]

// Slice from start up to index "3" [excluded]
aSlice := a[:3]

// Slice from index "2" [included], up to the end
aSlice := a[2:]

append (values)

Append only works with Slices.

When you add elements and the Slice's underlying Array can't hold it, a new Array with double the capacity is generated.

a := []int{1, 1}
fmt.Println(len(a), cap(a)) // 2 2

a = append(a, 1)
fmt.Println(len(a), cap(a)) // 3 4  -> Here capacity doubled

a = append(a, 1)
fmt.Println(len(a), cap(a)) // 4 4

You may append more than one value at a time.

a := []int{1, 1}

a = append(a, 1, 2, 3)

append (slices)

You can append/merge entire Slices also, with the ... operator (Similar to Typescript spread).

a := []int{1, 1}
b := []int{2, 2}

a = append(a, b...)

Removing elements

Removing the elements are done by slicing the Slice.

a := []int{1, 1}

// Removing the first element
a = a[1:]

make function

make(slice-type, slice-lenght, underlying-array-capacity)

Use the make function to initially pre-allocate and optionally fill a specific amount of space in a Slice.

If set the Slice will be filled with the default "null" value of the Slice type.

Ex.: []int Slice will be filled with zeros.

The pre-allocation to avoid Go to keep recreating bigger underlying arrays is only efficient if slice-length is 0.

Otherwise the these Array positions will be occupied with empty values.

a := make([]int, 5)
fmt.Println(a, len(a), cap(a)) // [0 0 0 0 0] 5 5

a := make([]int, 1, 10)
fmt.Println(a, len(a), cap(a)) // [0] 1 10

a := make([]int, 0, 10)
fmt.Println(a, len(a), cap(a)) // [] 0 10

Maps

Maps are key: value pairs of data, and have always dynamic size.

Just like Slices, Go will under the hood, recreate Maps when their memory capacity is reached.

Optimize this with make function.

Are Maps sortable thought??

Declare only

Inside [] is the Map key type.

Right beside, it is the value type.

Maps that are only declared will be "empty" and ocupy no memory.

var m map[string]int
var m map[string]int = map[string]int{}
m := map[string]int{}

Instanciate

m := map[string]int{
    "google": 1,
    "aws": 2,
}

Access value of map

Acessing keys that don't exist will return the "null" value of the value type.

No errors are generated.

m["google"]

Mutating the map

You can add new key: value pairs by using unexisting keys.

m["azure"] = 3

Edit existing key: value pairs by overwriting its value.

m["google"] = 11

Delete a key

Deleting unexisting keys produces no errors.

delete(m, "azure")

make function

make(map-type, size)

Pre-allocate more space in memory with make.

You can't really see the different, as in Slices, because Go manages this under the hood.

m := make(map[string]int, 5)
fmt.Println(m, len(m)) // [] 0
PreviousModules & PackagesNextStructs

Last updated 1 month ago

(to Stdout)

fmt.Printf
fmt.Sprintf