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#
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
| Function | Description |
|---|
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.)
| Function | Description |
|---|
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 |
| Function | Description |
|---|
math.Log(x) | Natural logarithm (ln) |
math.Log10(x) | Base-10 logarithm |
math.Log2(x) | Base-2 logarithm |
math.Exp(x) | e^x |
| Constant | Description | |
|---|
math.Pi | π (3.14159…) | |
math.E | Euler’s number | |
math.Sqrt2 | √2 | |
math.SqrtPi | √π | |
math.Ln2 | ln(2) | |
math.Ln10 | ln(10) | |
| Function | Description | |
|---|
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#
| Function | Description | |
|---|
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
| Function | Description |
|---|
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.