Map#

  • A map is a built-in data structure used to store key-value pairs.
  • Each key is unique and maps to a value.
  • Maps are unordered - iteration order is not guaranteed
  • Maps are reference types - passed by reference to functions
  • Not safe for concurrent use - use sync.Map or mutex for concurrent access
// Decleration
var m map[string]int // A declared map is `nil` until initialized. 
/*
- `string` → key type  
- `int` → value type  
*/


// Initialization
m := make(map[string]int)  // using make

m := map[string]int{  // using map literal 
	"apple": 10,  
	"banana": 20,  
}  


// Adding & Updating values
m["apple"] = 30  
m["orange"] = 15    
// If the key exists → value is updated.  
// If the key does not exist → a new entry is created.  


// Accessing values
value := m["apple"]
value, exists := m["apple"] // if value doesn't exist value=zero value & exists=false


// Deleting from map
delete(m, "apple")


// Iterate over map
for key, value := range m {  
	fmt.Println(key, value)  
}  


// Length of map - count of key value pairs exising
len(m)

Pointers#

  • A pointer is a variable that stores the memory address of another variable.
  • Pointers allow functions to modify the original value instead of working on a copy.
  • Go does not support pointer arithmetic.
  • A pointer stores a memory address.
  • & → address operator.
  • * → dereference operator.
  • slices & maps are already pointers
// Decleration
var p *int
// `p` → pointer variable  
// `*int` → pointer to an integer


x := 10  
p := &x  
// `x` → value  
// `&x` → memory address of `x`  
// `p` now stores the address of `x`  


// Dereferencing a pointer
x := 10  
p := &x  
fmt.Println(*p) // 10


// Modifying value using pointer
x := 10  
p := &x
*p = 20 // x = 20 now 


// Passing pointer to a function (pass by value, the catch is value is a pointer to a variable.)
func update(n *int) {  
	*n = 50  
}  
x := 10  
update(&x) // x updated to 50


// Creating a pointer using new
p := new(int) // Default value is 0 for int


// Pointer to a struct (go automatically dereferences struct pointer)
type Person struct {  
	name string  
	age int  
}
p := &Person{name: "John", age: 25}  
// Access using p.name & p.age, no need for (*p).name

Method#

  • Functions with special reciever
  • A method is a function associated with a specific type.
  • It allows you to define behavior for a type.
func (receiver Type) MethodName(parameters) returnType {  
// method body  
}


type Rectangle struct {  
	width int  
	height int  
}
func (r Rectangle) Area() int {  
	return r.width * r.height  
}
rect := Rectangle{width: 10, height: 5}  
area := rect.Area()
  • Value & Pointer receiver
  • When to use pointer receiver:
    • Need to modify the receiver
    • Receiver is a large struct (avoid copying)
    • Consistency (if some methods use pointer receivers, all should)
func (r Rectangle) Area() int {  // Value reciever, The method receives a **copy of the value**.
	return r.width * r.height  
}

func (r *Rectangle) Scale(factor int) {  // Pointer reciever, recieves a pointer to the type
	r.width = r.width * factor  
	r.height = r.height * factor  
}

Interfaces#

  • An interface defines a set of method signatures.
  • Any type that implements those methods automatically satisfies the interface.
  • Go uses implicit implementation (no implements keyword).
  • interfaces often end with er, like Reader, Writer, Stringer etc.
  • Since Go 1.18, any is an alias for interface{}
  • An interface value contains two things:
    • Concrete value
    • Type of the value
// Declaring a interface
type Shape interface {  
	Area() float64  
}
type Shape2 interface {  
	Area() float64  
	Perimeter() float64  
}
// Any type that defines `Area() float64` satisfies `Shape`.

// Implementing a interface
type Rectangle struct {  
	width float64  
	height float64  
}
func (r Rectangle) Area() float64 {  
	return r.width * r.height  
}

// Using an Interface
func PrintArea(s Shape) {  
	fmt.Println(s.Area())  
}  
  
rect := Rectangle{10, 5}  
PrintArea(rect)
  • Empty Interface - The empty interface has no methods. Can hold any value interface{}
var v interface{}  
v = 10  
v = "hello"
  • Type assertions - Used to extract the underlying value from an interface. if assertions fails then they cause panic(full termination of program)
// Type assertions
var v interface{}  
v = 10
v := i.(int)
v, ok := i.(int)

// Type Switches, Switch for type assertions
switch v := i.(type) {  
	case int:  
		fmt.Println("int", v)  
	case string:  
		fmt.Println("string", v)  
	default:  
		fmt.Println("unknown type")  
}

Error Interface#

  • Error interface
type error interface {
	Error() string
}

// usage
func DoSomething() (int, error) { 
	// ... 
}

// create a new error object
var ErrNotFound = errors.New("resource was not found")
// nil for no error

// Create custom error
type MyCustomError struct {
  message string
  details string
}
func (e *MyCustomError) Error() string {
  return fmt.Sprintf("%s, details: %s", e.message, e.details)
}
func someFunction() error {
  // ...
  return &MyCustomError{
    message: "...",
    details: "...",
  }
}

“math” package#

  • The math package provides functions and constants for mathematical operations
  • Documentation - https://pkg.go.dev/math
  • Common Math Functions
FunctionDescription
math.Abs(x)Absolute value
math.Sqrt(x)Square root
math.Pow(x, y)x raised to the power y
math.Pow10(n)10 raised to the power n
math.Ceil(x)Smallest integer ≥ x
math.Floor(x)Largest integer ≤ x
math.Round(x)Round to nearest integer
math.Trunc(x)Remove fractional part
math.Mod(x, y)Remainder of x / y
math.Max(x, y)Maximum of two numbers
math.Min(x, y)Minimum of two numbers
  • Trigonometric Functions (Angles are in radians, not degrees.)
FunctionDescription
math.Sin(x)Sine
math.Cos(x)Cosine
math.Tan(x)Tangent
math.Asin(x)Arc sine
math.Acos(x)Arc cosine
math.Atan(x)Arc tangent
  • Logarithmic Functions
FunctionDescription
math.Log(x)Natural logarithm (ln)
math.Log10(x)Base-10 logarithm
math.Log2(x)Base-2 logarithm
math.Exp(x)e^x
  • Common Constants
ConstantDescription
math.Piπ (3.14159…)
math.EEuler’s number
math.Sqrt2√2
math.SqrtPi√π
math.Ln2ln(2)
math.Ln10ln(10)
  • Special Values
FunctionDescription
math.NaN()Not a number
math.IsNaN(x)Check if value is NaN
math.Inf(sign)Positive or negative infinity
math.IsInf(x, sign)Check if value is infinity

“math/rand” package#

FunctionDescription
rand.Seed(seed)Sets the seed for random generator
rand.Int()Random non-negative integer
rand.Intn(n)Random integer in range [0, n)
rand.Int31()Random 31-bit integer
rand.Int63()Random 63-bit integer
rand.Float32()Random float32 in range [0.0, 1.0)
rand.Float64()Random float64 in range [0.0, 1.0)
rand.Perm(n)Random permutation of [0..n-1]
rand.Shuffle(n, swapFn)Randomly shuffles elements
rand.New(source)Creates a new random generator
rand.NewSource(seed)Creates a new seed source

rand.Int() // Any Int number
rand.Intn(10) // Any Int number between 0 and 10(exclusive)
rand.Float64() // any float64 number
  
rand.Perm(5) // slice of n elements with range [0, n)
  
nums := []int{1,2,3,4,5}  // Shuffle the existing list
rand.Shuffle(len(nums), func(i, j int) {  
  nums[i], nums[j] = nums[j], nums[i]  
})  
nums

“regexp” package#

import "regexp"

matched, _ := regexp.MatchString("go", "golang")
fmt.Println(matched) // true

re := regexp.MustCompile("[a-z]+")
fmt.Println(re.MatchString("hello123")) // true
fmt.Println(re.FindString("abc123xyz")) // abc
fmt.Println(re.FindAllString("abc123xyz456", -1)) // [abc xyz]
fmt.Println(re.ReplaceAllString("abc123xyz", "#")) // #123#
fmt.Println(re.Split("a,b,c", -1)) // [ , , ]

re = regexp.MustCompile(`[a-z]+\d*`)
b = re.MatchString("[a12]")       // => true
b = re.MatchString("12abc34(ef)") // => true
b = re.MatchString(" abc!")       // => true
b = re.MatchString("123 456")     // => false
FunctionDescription
regexp.MatchString(pattern, s)Checks if pattern matches string
regexp.Compile(pattern)Compiles a regular expression
regexp.MustCompile(pattern)Compiles regex and panics on error
re.MatchString(s)Checks if regex matches string
re.FindString(s)Returns first match
re.FindAllString(s, n)Returns all matches
re.ReplaceAllString(s, repl)Replaces matches with new string
re.Split(s, n)Splits string using regex

“stringer” interface#

  • Stringer is an interface for defining the string format of values. The interface consists of a single String method:
type Stringer interface {
    String() string
}

Types that want to implement this interface must have a String() method that returns a human-friendly string representation of the type.

  • similar to overriding the toString() method in Java.