string & “strings” package#
- A string in Go is an immutable sequence of bytes.
- Strings usually contain UTF-8 encoded text.
- Because strings are immutable, any modification creates a new string instead of changing the original one.
s := "Hello"
s[0] = "h" // invalid
var name string = "John" // Using explicit type
name := "John" // Using type inference
- String Concatenation - using the
+ operator
firstName := "John"
lastName := "Doe"
fullName := firstName + " " + lastName
- Escape Characters - Special characters can be used inside strings.
\n → New line\t → Tab\" → Double quote\\ → Backslash
- Raw Strings - use backticks (`) and preserve formatting. No escaping is required.
- String Length - Use the built-in
len() function. len() returns the number of bytes, NOT necessarily the number of characters.
s := "hello"
length := len(s)
strings Package - The strings package provides many utility functions for string manipulation.
| Function | Description | Example | Result |
|---|
strings.ToLower() | Converts all characters to lowercase | strings.ToLower(“HELLO”) | “hello” |
strings.ToUpper() | Converts all characters to uppercase | strings.ToUpper(“hello”) | “HELLO” |
strings.Compare() | Lexicographically compares two strings | strings.Compare(“abc”,“abc”) | 0 |
strings.Contains() | Checks if substring exists | strings.Contains(“hello world”,“world”) | true |
strings.ContainsAny() | Checks if any character from set exists | strings.ContainsAny(“team”,“ae”) | true |
strings.ContainsRune() | Checks if rune exists | strings.ContainsRune(“hello”,’e') | true |
strings.ContainsFunc() | Checks if any rune satisfies a condition | strings.ContainsFunc(“Hello”, unicode.IsUpper) | true |
strings.Count() | Counts occurrences of substring | strings.Count(“banana”,“a”) | 3 |
strings.HasPrefix() | Checks if string starts with prefix | strings.HasPrefix(“golang”,“go”) | true |
strings.HasSuffix() | Checks if string ends with suffix | strings.HasSuffix(“file.txt”,".txt") | true |
strings.Index() | Returns first occurrence index | strings.Index(“hello”,“l”) | 2 |
strings.LastIndex() | Returns last occurrence index | strings.LastIndex(“hello”,“l”) | 3 |
strings.Join() | Joins slice elements into a string | strings.Join([]string{“go”,“is”,“fun”}," “) | “go is fun” |
strings.Split() | Splits string into slice | strings.Split(“a,b,c”,”,") | [“a”,“b”,“c”] |
strings.Replace() | Replaces substring occurrences (limited count) | strings.Replace(“foo bar foo”,“foo”,“baz”,1) | “baz bar foo” |
strings.ReplaceAll() | Replaces all occurrences | strings.ReplaceAll(“foo bar foo”,“foo”,“baz”) | “baz bar baz” |
strings.Trim() | Removes specified characters from both ends | strings.Trim("!!hello!!","!") | “hello” |
strings.TrimSpace() | Removes leading and trailing spaces | strings.TrimSpace(" hello “) | “hello” |
strings.Lines() | Returns iterator over lines | strings.Lines(“a\nb\nc”) | line iterator |
var builder strings.Builder
builder.WriteString("Hello")
builder.WriteString(", ")
builder.WriteString("world!")
fmt.Println(builder.String()) // Output: Hello, world!
rune#
- A rune represents a Unicode code point.
rune is an alias for int32. - It is commonly used to represent individual Unicode characters.
- Strings in Go are byte sequences (UTF-8). Some characters require multiple bytes, so indexing a string gives bytes, not characters.
rune helps correctly work with Unicode characters.
s := "Go"
b := s[0] // byte
r := rune(s[0]) // rune
// rune literal
r := 'A'
r := '你'
r := '🙂'
| Type | Size | Usage | |
|---|
| byte | 8-bit | raw data / ASCII | |
| rune | 32-bit | Unicode character | |
- Iterating Over Runes in a String - Using
range automatically decodes UTF-8 into runes.
s := "Hello"
for i, r := range s {
fmt.Println(i, r)
}
//Converting string to rune
s := "hello"
r := []rune(s) // This allows **safe character indexing**.
r[0]
// Rune to string
r := 'A'
s := string(r)
// Check if its a unicode char
unicode.IsLetter(r)
// Length
s := "你好"
len(s) // Length in bytes
length := len([]rune(s)) // Actual character length i.e converts the string into **Unicode code points** then count.
import "unicode/utf8"
length := utf8.RuneCountInString(s) // actual length
Operators#
- Arithmetic
- Assignment
- Comparison
- Logical
- Increment / Decrement
- Bitwise
Arrays & Slices#
- Arrays
- Arrays are fixed-size collections of elements of the same type.
- Arrays have fixed size.
- Size is part of the array type.
- Arrays are value types (copied when passed to functions).
- Array type includes both size and element type:
[5]int and [10]int are different types
var arr [5]int // Decleration
arr := [5]int{1, 2, 3, 4, 5} // Initialization
arr := [...]int{1, 2, 3, 4} // Size Inference
arr[0], arr[1] // Accessing Elements
arr[2] = 10 // Updating Elements
len(arr) // Length of the array
var a = [4]int{0: 10, 3: 2} // Specific elements are initialized rest all, default value
- Slices
- Slices are dynamic, flexible views over arrays.
- They are used more frequently than arrays in Go.
- Syntax
- slice[start:end]
- Rules
start → inclusiveend → exclusive- default start →
0 - default end →
len(slice)
- len(s), cap(s)
len → number of elementscap → underlying array capacity
- append function returns a new Slice
- Slices internally reference an underlying array.
- No direct delete functionality exists. To delete the elements use the append & slicing functionality to achieve the same.
var s []int // Decleration
s := []int{1, 2, 3, 4} // Initialization
arr := [5]int{1,2,3,4,5}
s := arr[1:4] // Creating slices from array
s := []int{0,1,2,3,4,5}
s[1:4] // slice starting from index 1 to 3
s[:3] // slice starting from start to index 2
s[2:] // slice starting from index 2 to end
s[:] // slice starting from start to end
s := []int{1,2,3}
s = append(s, 4) // Add single element
s = append(s, 5, 6, 7) // Add multiple element
b := []int{3,4}
a = append(a, b...) // Add another slice
s := make([]int, 5) // creating with preferred len & capacity
s := make([]int, 5, 10)
| Feature | Arrays | Slices | |
|---|
| Size | Fixed | Dynamic | |
| Declaration | [5]int | []int | |
| Usage | Rare | Very common | |
| Passed to functions | Copied | Reference-like | |
| Memory | Entire array | Reference to array | |
copy(destination, source) // works on slices
var s = []int{12, 23, 34}
var sn = make([]int, len(s)) var n = copy(sn, s) // var n is the number of copied elements
Struct#
- A struct is a user-defined type that groups related fields (variables) together.
- It is similar to a class in other languages, but without inheritance.
// Defining
type Person struct { // struct type
name string // Fields
age int
}
// Creating instance
p := Person{
name: "John",
age: 25,
}
p2 := Person{"John", 25}
p3 := new(Person)
// Accessing fields & modifying
p.name
p.age
p.name = "New Name"
- Exported vs Unexported Fields, Field visibility depends on capitalization.
| Field Name | Visibility |
|---|
| name | private (same package only) |
| Name | exported (accessible outside package) |
- Struct with Constructor Pattern, Go does not have constructors, but factory functions are commonly used.
func NewPerson(name string, age int) Person {
return Person{
name: name,
age: age,
}
}
p := NewPerson("John", 25)
- Struct Comparison - structs can be compared if all fields are comparable.
p1 := Person{"John", 25}
p2 := Person{"John", 25}
p1 == p2 // true
- Anonymous Struct - Structs can be created without defining a type.
p := struct {
name string
age int
}{
name: "John",
age: 25,
}
Looping#
- Basic used when the number of iterations is known.
/*for init; condition; post {
loop body
} */
for i := 0; i < 5; i++ {
fmt.Println(i)
}
i := 0
for i < 5 {
fmt.Println(i)
i++
}
- Infinite Loop - Runs indefinitely until stopped with
break or return.
for {
fmt.Println("Running forever")
}
- for-range Loop - Used to iterate over arrays, slices, maps, strings, and channels.
items := []string{"a", "b", "c"}
for index, value := range items {
fmt.Println(index, value)
}
- Ignoring Values in range - Use
_ to ignore index or value.
// Ignoring Index
for _, value := range items {
fmt.Println(value)
}
// Ignore value
for index, _ := range items {
fmt.Println(index)
}
- break Statement - Used to exit a loop immediately.
for i := 0; i < 10; i++ {
if i == 5 {
break
}
fmt.Println(i)
}
- continue Statement - Skips the current iteration and moves to the next one.
for i := 0; i < 5; i++ {
if i == 2 {
continue
}
fmt.Println(i)
}
“time” package#
- The time package provides functionality for working with time, dates, durations, and formatting. Documentation - https://pkg.go.dev/time
- Current Time - Get the current local time.
now := time.Now() // Returns time.Time
t := time.Date(
2024, // year
time.January, // month
10, // day
15, // hour
30, // minutes
0, // seconds
0, // nanoseconds
time.UTC, // location
)
- Time Parsing (String → time) - Convert a string into time.Time using
Parse.- Go uses a reference time layout => Mon Jan 2 15:04:05 MST 2006
date := "Tue, 09/22/1995, 13:00"
layout := "Mon, 01/02/2006, 15:04"
t, err := time.Parse(layout, date)
- Time Formatting (time → String) - Convert
time.Time to a string.
t := time.Now()
formatted := t.Format("2006-01-02 15:04:05")
t1.After(t2) // true if `t1` is after `t2`
t1.Before(t2) // true if `t1` is before `t2`
t1.Equal(t2) // Checks if both times are equal
- Time Duration - Duration represents the elapsed time between two instants.
duration := time.Hour
duration := 30 * time.Minute
Common durations
| Constant | Meaning |
|---|
time.Nanosecond | 1 nanosecond |
time.Microsecond | 1 microsecond |
time.Millisecond | 1 millisecond |
time.Second | 1 second |
time.Minute | 1 minute |
time.Hour | 1 hour |
start := time.Now()
// code execution
elapsed := time.Since(start) // Performance measurement
- Adding or Subtracting Time
t := time.Now()
future := t.Add(2 * time.Hour)
diff := t1.Sub(t2) // Returns time.Duration
- Unix Time - Unix timestamp represents seconds since Jan 1, 1970 (UTC).
t := time.Now()
ts := t.Unix() // Get Unix time
t := time.Unix(1700000000, 0) // Create time from unix