Go Fundamentals: Slices and Strings

Introduction

Welcome to this course on Revisiting Go Basics, part of the Fundamental Coding Interview Preparation in Go course path!

Before delving into Go programming for interview preparation, let's explore some foundational concepts in Go. We'll focus on Go's slices and examine how strings are handled. These tools are crucial for organizing multiple elements, such as numbers or letters, within a single structure.

Understanding Go's Slices

Go's slices are dynamically-sized, flexible views into the elements of an array. Unlike arrays, slices are dynamic and allow you to change their contents, providing significant flexibility. Let’s see how to create and modify slices:

package main

import "fmt"

func main() {
    // Defining a slice
    mySlice := []int{1, 2, 3, 4}
    
    // Printing the first (0-indexed) element of the slice
    fmt.Println(mySlice[0])
    
    // Changing the first element of the slice
    mySlice[0] = 100

    // Now, mySlice contains {100, 2, 3, 4}
    fmt.Println(mySlice)
}

In this simple snippet:

  • We define mySlice as a slice of integers, containing the elements 1, 2, 3, 4.
  • We access the first element via indexing using mySlice[0]
  • We update the first element by assigning a new value mySlice[0] = 100

Diving Into Slices

Slices in Go serve as a powerful abstraction over arrays. They allow you to efficiently manage collections of data, providing several built-in functions for manipulation. These operations include appending elements, slicing, and removing elements.

append() is a function that adds a new element to the end of a slice, effectively increasing its size. To remove elements, you can employ slicing techniques; for example, mySlice[1:] selects all elements of mySlice starting from index 1, effectively removing the element at index 0.

For many other operations, such as finding an element in a slice, the idiomatic way in Go to carry out such operations is to simply employ for loops. The example below illustrates these operations:

package main

import "fmt"


func main() {
    // Creating a slice
    fruits := []string{"apple", "banana", "cherry"}
    
    // Adding a new element using append
    fruits = append(fruits, "date")
    
    // Inserting an element by manual slicing
    fruits = append(fruits[:1], append([]string{"bilberry"}, fruits[1:]...)...)
    
    // Finding the position of 'banana' and removing it
    for i, fruit := range fruits {
        if fruit == "banana" {
            fruits = append(fruits[:i], fruits[i+1:]...)
            break
        }
    }
    
    // Accessing elements using indexing
    firstFruit := fruits[0]  // "apple"
    lastFruit := fruits[len(fruits)-1]  // "date"

    // Now, fruits equals {"apple", "bilberry", "cherry", "date"}
    fmt.Println(fruits)
    fmt.Println(firstFruit, lastFruit)
}

Here, append() adds "date" to the end of the fruits slice. Manual slicing is utilized to insert "bilberry", and a loop helps locate and remove "banana". The slicing operation for inserting "bilberry" involves breaking the slice and reconstructing it with the new element. The three dots (...) notation in fruits[1:]... is called the "variadic argument" expansion. It allows you to pass elements of fruits[1:] as separate arguments to the append() function, effectively appending each element individually.

Sign up

Join the 1M+ learners on CodeSignal

Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal