Primitives

Booleans

Booleans:
- Values are true or false
- NOT an alias for other types (I.E int) unlike in other programming languages
- Zero value is false


// Boolean example
func main() {
  n := 1 == 1
  m := 1 == 2
  fmt.Printf("%v, %T\n", n, n)
  fmt.Printf("%v, %T\n", m, m)
}

Numeric Types

Numeric Types:
- Signed Integers:
  - int types have varying sizes, but it is always a minimum of 32 bits
  - 8 bit (int8) through 64 bit (int64)
- Unsigned integers:
  - 8 bit (byte and uint8) through 32 bit (uint32)

- Arithmetic operations:
  - Addition, subtraction, multiplication, division, remainder


// Arithmetic example
func main() {
  a := 10
  b := 3
  fmt.Printf(a + b)
  fmt.Printf(a - b)
  fmt.Printf(a * b)
  fmt.Printf(a / b)
  fmt.Printf(a % b)
}

Bitwise Operations

Bitwise Operation Types:
 - And, or, xor, and not


// Bitwise operations example
func main() {
  a := 10 // 1010
  b := 3  // 0011

  //// And operator
  // Bits are set if both numbers has that bit
  fmt.Printf(a & b)  // 0010 = 2

  //// Or operator
  // Bits are set if they are in EITHER number
  fmt.Printf(a | b)  // 1011 = 11

  //// Xor operator
  // Bits are set if one number has it, BUT NOT both
  fmt.Printf(a ^ b)  // 1001 = 9

  //// And Not operator
  // Bits are set if neither one of the numbers has that bit
  fmt.Printf(a &^ b) // 0100 = 8
}

// BONUS: Bitshifting example
func main() {
  a := 10

  // Shifting to the left
  fmt.Printf(a << 3) // 2^3 * 2^3 = 64

  // Shifting to the right
  fmt.Printf(a >> 3) // 2^3 / 2^3 = 2^0
}

Floating Point Numbers

Floating Point Numbers:
- Follows IEEE-754 standard
- Zero value is 0
- 32 and 64 bit versions
- Literal styles:
  - Decimal (3.14)
  - Exponential (13e18 or 2E10)
  - Mixed (13.7e12)
- Arithmetic operations:
  - Addition, subtraction, multiplication, division


// Floating point number example
// NOTE: These variables will be initialized as float64
func main() {
  n := 3.14
  n = 13.7e72
  n = 2.1E14

  fmt.Printf("%v, %T", n, n)
}

Strings

Text Types:
- Strings:
  - UTF-8
  - Immutable
  - Can be concatenated with plus (+) operator
  - Can be converted to []byte

- Rune:
  - UTF-32
  - Alias for int32
  - Special methods normally required to process
    - I.E strings.Reader#ReadRune


// String example
func main() {
  s := "this is a string"

  fmt.Printf("%v, %T\n", string(s[2]), s)
}


Consts & Iota

Constants:
- Immutable, but can be shadowed
- Replaced by the compiler at compile time
  - Value must be calculable at compile time
- Named like variables:
  - PascalCase for exported constants
  - camelCase for internal constants
- Typed constants work like immutable variables
  - Can interoperate only with same type
- Untyped constants work like literals
  - Can interoperate with similar types


func main() {
  const myConst int = 42
  fmt.Printf("%v, %T\n", myConst, myConst)

  // Const variables can hold all the primitive times
  const a int = 14
  const b string = "foo"
  const c float32 = 3.14
  const d bool = true
  fmt.Printf("%v\n", a)
  fmt.Printf("%v\n", b)
  fmt.Printf("%v\n", c)
  fmt.Printf("%v\n", d)
}

Enumerated Constants:
- Special symbol iota allows related constants to be created easily
- Iota starts at 0 in each const block and increments by one
  - After the first instance of Iota in a const block, you do not need the other variable declarations to say iota
- Watch out for constant values that match zero values for variables

Enumerated Expressions:
- Operations that can be determined at compilation time are allowed:
  - Arithmetic
  - Bitwise operations
  - Bitshifting

//// Basic Iota example
// You can put a iota in a const block too
const (
  a = iota
  b
  c
)

const (
  a2 = iota
)

func main() {
// Will print out 0, 1, 2, each on new lines.
  fmt.Printf("%v\n", a)
  fmt.Printf("%v\n", b)
  fmt.Printf("%v\n", c)
  
  // A seperate iota instance
  fmt.Printf("%v\n", a2)
}

//// Iota Example #1: Basic specialist
const (
  // "_" just means "this is a throwaway, don't use this variable"
  _ = iota
  catSpecialist
  dogSpecialist
  snakeSpecialist
)

func main() {
  var specialistType int = catSpecialist
  fmt.Printf("%v\n", specialistType == catSpecialist)
}

ae

//// Iota Example #2: File size calculus
const (
  _ = iota
  KB = 1 << (10 * iota)
  MB
  GB
  TB
  PB
  EB
  ZB
  YB
)

func main() {
  fileSize := 4000000000.
  fmt.Printf("%.2fGB\n", fileSize/GB)
}

ae

//// Iota Example #3: Fancy manager key access
const (
  isAdmin = 1 << iota
  isHeadquarters
  canSeeFinancials

  canSeeAfrica
  canSeeAsia
  canSeeEurope
  canSeeNorthAmerica
  canSeeSouthAmerica
)

func main() {
  var roles byte = isAdmin | canSeeFinancials | canSeeEurope
  fmt.Printf("%b\n", roles)
  fmt.Printf("Is Admin? %v\n", isAdmin & roles == isAdmin)
  fmt.Printf("Is HQ? %v\n", isHeadquarters & roles == isHeadquarters)
}

Arrays & Slices

Arrays:
- Collection of items with same type (no mixing types)
- Fixed size
- Declaration styles:
  - a := [3]int{1, 2, 3}
  - a := [...]int{1, 2, 3}
  - var a [3]int
- Accessed via zero-based index
  - a := [3]int{1, 3, 5} // a[1] == 3
- len function returns size of array
- Copies refer to different underlying data

Slices:
- Backed by array
- Creation styles:
- Slice existing array or slice
- Literal style
- Via make function
  - a := make([]int, 10) // Creates slice with length and capacity == 10
  - a := make([]it, 10, 100) // Creates slice with length == 10 and capacity == 100
- "len" function returns length of slice
- "cap" function returns length of underlying capacity	
- Use append function to add elements to slices
  - May cause expensive copy operation if underlying array is too small
- Copies refer to same underlying array

By Levi

Leave a Reply

Your email address will not be published. Required fields are marked *