Go Tutorial - Section 4

Welcome back to the Go Tutorial series. As usual, I have my assumptions before starting this section. I assume you have already completed your assignment and have got feedback. If you haven't gone through the assignment, it would be advisable to go here. If you have submitted the assignment for feedback and haven't got one, please continue with this section without worries, the feedback will reach you as soon as possible. In this section, we will cover the below-mentioned topics.

  1. Arrays

  2. Slice.

  3. Range

  4. Strings


Arrays


Go programming language provides a data structure called the array, which can store a fixed-size sequential collection of elements of the same type. An array is used to store a collection of data, but it is often more useful to think of an array as a collection of variables of the same type.


Instead of declaring individual variables, such as number0, number1, ..., and number99, you declare one array variable such as numbers and use numbers[0], numbers[1], and ..., numbers[99] to represent individual variables. A specific element in an array is accessed by an index.


All arrays consist of contiguous memory locations. The lowest address corresponds to the first element and the highest address to the last element.


The elements of the array are indexed by using the [] index operator with their zero-based position, means the index of the first element isarray[0]and the index of the last element isarray[len(array)-1].


Declaring and accessing an array


There are two ways to declare an array.


Using var keyword

In Go language, an array is created using the var keyword of a particular type with name, size, and elements. Syntax

var array_name[length]Type

Pointers:

  1. Arrays are mutable. You can use array[index] syntax to the left-hand side of the assignment to set the elements of the array at the given index.

  2. You can access the elements of the array by using the index value or by using for loop.

  3. The length of the array is fixed and unchangeable.

  4. You are allowed to store duplicate elements in an array.

Example

package main 
  
import "fmt"
  
func main() { 
  
  // Creating an array of string type  
  // Using var keyword 
  var myarr[3]string
  
  // Elements are assigned using index 
  myarr[0] = "Aman"
  myarr[1] = "Aman Sinha"
  myarr[2] = "Go Tutorial"
  
  // Accessing the elements of the array  
  // Using index value 
  fmt.Println("Elements of Array:") 
  fmt.Println("Element 1: ", myarr[0]) 
  fmt.Println("Element 2: ", myarr[1]) 
  fmt.Println("Element 3: ", myarr[2]) 
} 

Output

Elements of Array:
Element 1:  Aman
Element 2:  Aman Sinha
Element 3:  Go Tutorial

Using short-hand notations

Arrays can also declare using the shorthand declaration. Syntax

array_name:= [length]Type{item1, item2, item3,...itemN}

Example

 package main 

import "fmt"

func main() { 

 // Shorthand declaration of array 
 arr:= [4]string{"Aman", "Aman Sinha", "Go Tutorial"} 

 // Accessing the elements of 
 // the array Using for loop 
 fmt.Println("Elements of the array:") 

 for i:= 0; i < 3; i++{ 
   fmt.Println(arr[i]) 
 } 

} 

Output

Elements of the array:
Aman
Aman Sinha
Go Tutorial

Multi-Dimensional Arrays


Here is the general form of a multidimensional array declaration:

var variable_name [SIZE1][SIZE2]...[SIZEN] variable_type

To keep things simple, we will understand how a two-dimensional array works.

A two-dimensional array is, in essence, a list of one-dimensional arrays.

To declare a two-dimensional integer array of size [x, y], you would write something like this

var arrayName [ x ][ y ] variable_type

Where variable_type can be any valid Go data type and arrayName will be a valid Go identifier. A two-dimensional array can be thought as a table which will have x number of rows and y number of columns.

Thus, every element in the array a is identified by an element name of the form a[ i ][ j ], where a is the name of the array, and i and j are the subscripts that uniquely identify each element in a.

Example

package main

import "fmt"

func main() {
   /* an array with 5 rows and 2 columns*/
   var a = [5][2]int{ {0,0}, {1,2}, {2,4}, {3,6},{4,8}}
   var i, j int

   /* output each array element's value */
   for  i = 0; i < 5; i++ {
      for j = 0; j < 2; j++ {
         fmt.Printf("a[%d][%d] = %d\n", i,j, a[i][j] )
      }
   }
}

Output

a[0][0]: 0
a[0][1]: 0
a[1][0]: 1
a[1][1]: 2
a[2][0]: 2
a[2][1]: 4
a[3][0]: 3
a[3][1]: 6
a[4][0]: 4
a[4][1]: 8

You can have arrays with any number of dimensions, although it is likely that most of the arrays you create will be of one or two dimensions.


Slice


In Go language slice is more powerful, flexible, convenient than an array, and is a lightweight data structure. Slice is a variable-length sequence which stores elements of a similar type, you are not allowed to store different type of elements in the same slice. It is just like an array having an index value and length, but the size of the slice is resized they are not in fixed-size just like an array. Internally, slice and an array are connected with each other, a slice is a reference to an underlying array. It is allowed to store duplicate elements in the slice. The first index position in a slice is always 0 and the last one will be (length of slice – 1).


Go Slice is an abstraction over Go Array. Go Array allows you to define variables that can hold several data items of the same kind but it does not provide any inbuilt method to increase its size dynamically or get a sub-array of its own. Slices overcome this limitation. It provides many utility functions required on Array and is widely used in Go programming.


A slice is declared just like an array, but it doesn’t contain the size of the slice. So it can grow or shrink according to the requirement. Syntax

[]T
or 
[]T{}
or 
[]T{value1, value2, value3, ...value n}

Components of a slice

A slice contains three components:

  • Pointer: The pointer is used to points to the first element of the array that is accessible through the slice. Here, it is not necessary that the pointed element is the first element of the array.

  • Length: The length is the total number of elements present in the array.

  • Capacity: The capacity represents the maximum size up to which it can expand.

Example


package main 
  
import "fmt"
  
func main() { 
  
    // Creating an array 
    arr := [7]string{"This", "is", "the", "tutorial", 
                         "of", "Go", "language"} 
  
    // Display array 
    fmt.Println("Array:", arr) 
  
    // Creating a slice 
    myslice := arr[1:6] 
  
    // Display slice 
    fmt.Println("Slice:", myslice) 
  
    // Display length of the slice 
    fmt.Printf("Length of the slice: %d", len(myslice)) 
  
    // Display the capacity of the slice 
    fmt.Printf("\nCapacity of the slice: %d", cap(myslice)) 
}

Output

Array: [This is the tutorial of Go language]
Slice: [is the tutorial of Go]
Length of the slice: 5
Capacity of the slice: 6

In the above example, we create a slice from the given array. Here the pointer of the slice points to index 1 because the lower bound of the slice is set to one. Hence, it starts accessing elements from index 1. The length of the slice is 5, which means the total number of elements present in the slice is 5 and the capacity of the slice 6 means it can store a maximum of 6 elements in it.


How to create a slice?


A slice, in Go, can be created in the following ways.


Using slice literals

The creation of slice literal is just like an array literal, but with one difference you are not allowed to specify the size of the slice in the []


Example

package main 
  
import "fmt"
  
func main() { 
  
    // Creating a slice 
    // using the var keyword 
    var my_slice_1 = []string{"This", "is", "Go"} 
  
    fmt.Println("My Slice 1:", my_slice_1) 
  
    // Creating a slice 
    //using shorthand declaration 
    my_slice_2 := []int{12, 45, 67, 56, 43, 34, 45} 
    fmt.Println("My Slice 2:", my_slice_2) 
}

Output

My Slice 1: [This is Go]
My Slice 2: [12 45 67 56 43 34 45]

Using an array For creating a slice from the given array first you need to specify the lower and upper bound, which means slice can take elements from the array starting from the lower bound to the upper bound. It does not include the elements above from the upper bound.


Example

package main

import "fmt"

func main() {

    // Creating an array
    arr := [4]string{"This", "is", "Go", "Tutorial"}

    // Creating slices from the given array
    var my_slice_1 = arr[1:2]
    my_slice_2 := arr[0:]
    my_slice_3 := arr[:2]
    my_slice_4 := arr[:]

    // Display the result
    fmt.Println("My Array: ", arr)
    fmt.Println("My Slice 1: ", my_slice_1)
    fmt.Println("My Slice 2: ", my_slice_2)
    fmt.Println("My Slice 3: ", my_slice_3)
    fmt.Println("My Slice 4: ", my_slice_4)
}

Output

My Array:  [This is Go Tutorial]
My Slice 1:  [is]
My Slice 2:  [This is Go Tutorial]
My Slice 3:  [This is]
My Slice 4:  [This is Go Tutorial]

Using an already existing slice

For creating a slice from the given slice first you need to specify the lower and upper bound, which means slice can take elements from the given slice starting from the lower bound to the upper bound. It does not include the elements above from the upper bound.


Example

package main 
  
import "fmt"
  
func main() { 
  
    // Creating s slice 
    oRignAl_slice := []int{90, 60, 40, 50, 
        34, 49, 30} 
  
    // Creating slices from the given slice 
    var my_slice_1 = oRignAl_slice[1:5] 
    my_slice_2 := oRignAl_slice[0:] 
    my_slice_3 := oRignAl_slice[:6] 
    my_slice_4 := oRignAl_slice[:] 
    my_slice_5 := my_slice_3[2:4] 
  
    // Display the result 
    fmt.Println("Original Slice:", oRignAl_slice) 
    fmt.Println("New Slice 1:", my_slice_1) 
    fmt.Println("New Slice 2:", my_slice_2) 
    fmt.Println("New Slice 3:", my_slice_3) 
    fmt.Println("New Slice 4:", my_slice_4) 
    fmt.Println("New Slice 5:", my_slice_5) 
}

Output

Original Slice: [90 60 40 50 34 49 30]
New Slice 1: [60 40 50 34]
New Slice 2: [90 60 40 50 34 49 30]
New Slice 3: [90 60 40 50 34 49]
New Slice 4: [90 60 40 50 34 49 30]
New Slice 5: [40 50]

Using make() function

This function takes three parameters, i.e, type, length, and capacity. Here, capacity value is optional. It assigns an underlying array with a size that is equal to the given capacity and returns a slice which refers to the underlying array. Generally, make() function is used to create an empty slice.


Example

package main 
  
import "fmt"
  
func main() { 
  
    // Creating an array of size 7 
    // and slice this array  till 4 
    // and return the reference of the slice 
    // Using make function 
    var my_slice_1 = make([]int, 4, 7) 
    fmt.Printf("Slice 1 = %v, \nlength = %d, \ncapacity = %d\n", 
                   my_slice_1, len(my_slice_1), cap(my_slice_1)) 
  
    // Creating another array of size 7 
    // and return the reference of the slice 
    // Using make function 
    var my_slice_2 = make([]int, 7) 
    fmt.Printf("Slice 2 = %v, \nlength = %d, \ncapacity = %d\n", 
                   my_slice_2, len(my_slice_2), cap(my_slice_2)) 
      
} 

Output

Slice 1 = [0 0 0 0], 
length = 4, 
capacity = 7
Slice 2 = [0 0 0 0 0 0 0], 
length = 7, 
capacity = 7

How to iterate over slice? There are multiple ways to iterate over a slice. One method is the same as the array iteration using index value inside []. I will not be repeating the same thing. Other ways to iterate are mentioned below.


Using range in a loop

It is allowed to iterate over a slice using a range in the loop. Using range in the for loop, you can get the index and the element value

package main 
  
import "fmt"
  
func main() { 
  
    // Creating a slice 
    myslice := []string{"This", "is", "the", "tutorial", 
                                 "of", "Go", "language"} 
  
    // Iterate slice 
    // using range in for loop 
    for index, ele := range myslice { 
        fmt.Printf("Index = %d and element = %s\n", index+3, ele) 
    } 
} 

Output

Index = 3 and element = This
Index = 4 and element = is
Index = 5 and element = the
Index = 6 and element = tutorial
Index = 7 and element = of
Index = 8 and element = Go
Index = 9 and element = language

Using a blank identifier

In the range for loop, if you don’t want to get the index value of the elements then you can use blank space(_) in place of index variable.

package main 
  
import "fmt"
  
func main() { 
  
    // Creating a slice 
    myslice := []string{"This", "is", "the", 
        "tutorial", "of", "Go", "language"} 
  
    // Iterate slice 
    // using range in for loop 
    // without index 
    for _, ele := range myslice { 
        fmt.Printf("Element = %s\n", ele) 
    } 
} 

Output

Element = This
Element = is
Element = the
Element = tutorial
Element = of
Element = Go
Element = language

Range


The range keyword is used in for loop to iterate over items of an array, slice, channel or map. With array and slices, it returns the index of the item as an integer. With maps, it returns the key of the next key-value pair. Range either returns one value or two. If only one value is used on the left of a range expression, it is the 1st value in the following table.

PS: Do not worry about maps and channels right now. We will cover them later. Example

package main

import "fmt"

func main() {
   /* create a slice */
   numbers := []int{0,1,2,3,4,5,6,7,8} 
   
   /* print the numbers */
   for i:= range numbers {
      fmt.Println("Slice item",i,"is",numbers[i])
   }
 }

Output

Slice item 0 is 0
Slice item 1 is 1
Slice item 2 is 2
Slice item 3 is 3
Slice item 4 is 4
Slice item 5 is 5
Slice item 6 is 6
Slice item 7 is 7
Slice item 8 is 8

Strings


Strings, which are widely used in Go programming, are a read-only slice of bytes. In the Go programming language, strings are slices. The Go platform provides various libraries to manipulate strings.

  • unicode

  • regexp

  • strings

How to create a string?


The easiest way to create a string is given below:

var name = "Aman Sinha"

Whenever it encounters a string literal in your code, the compiler creates a String object with its value in this case, "Aman Sinha'.

A string literal holds a valid UTF-8 sequence called runes. A String holds arbitrary bytes. The string literal is immutable. It means that once it is created, a string literal cannot be changed. String Length

len(str) method returns the number of bytes contained in the string literal.


package main

import "fmt"

func main() {
   var greeting =  "Hello world!"
   
   fmt.Printf("String Length is: ")
   fmt.Println(len(greeting))  
}

This would produce the following result

String Length is : 12

String Concatenation

The strings package includes a method join for concatenating multiple strings.

strings.Join(sample, " ")

Join concatenates the elements of an array to create a single string. The second parameter is a separator which is placed between the elements of the array.

package main

import ("fmt" "math" )"fmt" "strings")

func main() {
   greetings :=  []string{"Hello","world!"}   
   fmt.Println(strings.Join(greetings, " "))
}

This would produce the following result

Hello world!

This brings me to the end of this section. Assignment to follow.

 

+919853340643

©2020 by Aman Sinha.