We frequently need to work with several values.
Before introducing Array, we must first understand how memory works.
Values in "Computer Memory" are stored in memory cells.
Each memory cell takes up one byte.
| __ | __ | __ | __ | __ | __ | __ | __ | __ | __ |
|cell| <= 1 byte
Variables can be assigned to different memory locations.
1001 memory cell 1006 memory cell
↓ ↓
| __ | 0 | __ | __ | __ | __ | 0 | __ | __ | __ |
↑ ↑
var age1 byte var age2 byte
An array's items are stored in contiguous memory cells.
From 1001 to 1002, it is a single array value
1001 1002 memory cell
↓ ↓
| __ | 0 | 0 | __ | __ | __ | __ | __ | __ | __ |
_______
↑
var ages [2]byte
Accessing values with contiguous memory cells is efficient for the CPU.
Let's look at the syntax.
The size of an array is indicated by the number enclosed in square brackets.
An array's size is equal to the sum of its items.
[2]byte => 2 * 1 byte = 2 bytes
[2]int16 => 2 * 2 byte = 4 bytes
The most crucial thing to remember is that the array size is fixed.
We won't be able to update it later.
Uninitialized array elements will be set to "Zero Values" by Go.
Each array element is a variable with no name.
Furthermore, Go will not allow you to directly access the memory address.
Instead, Go provides a "index expression" that allows us to specify the element of an array we want to access.
var ages [2]byte
ages[0] = 5
Looping an array
"range" can be used to traverse across an array.
for _, g := range greetings {
g += " has been changed!"
fmt.Println(g)
}
fmt.Printf("%q", greetings)
"range" will create a copy of the original array.
As a result, changing 'item' inside the range block has no effect on the original array.
You can alter the original array by using an index from the "range" array.
for i, _ := range greetings {
greetings[i] += " has been changed!"
}
fmt.Printf("%q\n", greetings)
How to create an array?
var greetings [3]string
greetings[0] = "Hello"
greetings[1] = "How are you"
greetings[2] = "Good"
Is this the only method for creating and assigning elements to an array?
This method can be used to generate and initialize a new array with the specified values.
var greetings = [3]string{
"Hello",
"How are you",
"Good",
}
We can even simplify it as seen below.
It is recommended that you use this format if you already have the element.
greetings := [3]string{
"Hello",
"How are you",
"Good",
}
It is called "Array Literal" on the right side.
One of the composite literals is array literal.
Composite Literals are used to generate new composite values (like arrays) on the fly.
Format:
type{
item,
item,
item
}
Go can automatically determine the length of an array by using 'ellipsis'.
greetings := [...]string{
"Hello",
"How are you",
"Good",
}
Comparing arrays?
When the types of arrays are the same, they are similar.
Arrays are equal when their elements are equal, which means that Go will compare each array element one by one.
To illustrate the distinction, consider bellows.
Ex1:
arr1 := [3]int{
1, 2, 3,
}
arr2 := [3]int{
1, 2, 3,
}
fmt.Println(arr1 == arr2)
true
Ex2:
arr1 := [3]int{
1, 2, 3,
}
arr2 := [3]int{
1, 4, 3,
}
fmt.Println(arr1 == arr2)
false
Ex3:
arr1 := [3]int{
1, 2, 3,
}
arr2 := [4]int{
1, 2, 3, 4,
}
fmt.Println(arr1 == arr2)
arr1 == arr2 (mismatched types [3]int and [4]int)
Assign an array to another one?
Only arrays of the same type can be assigned.
When we assign one array to another, Go creates a new memory location for the new array.
As a result, the old and new arrays are not linked.
arr1 := [2]byte{
1, 2,
}
arr2 := arr1
arr2[0] = 9
fmt.Printf("%d\n", arr1)
fmt.Printf("%d\n", arr2)
Result:
Memory cells:
[1 2]
[9 2]
Memory cells:
| __ | 1 | 2 | __ | __ | __ | 9 | 2 | __ | __ |
_______ _______
↑ ↑
arr1 arr2
Array of array
Assume we want to calculate the sum of all the values in two arrays.
The simple version will look like:
sum := byte(0)
cost1 := [3]byte{1, 2, 3}
cost2 := [3]byte{4, 5, 6}
for _, c1 := range cost1 {
sum += c1
}
for _, c2 := range cost2 {
sum += c2
}
fmt.Println(sum)
Go provides an additional structure for this circumstance.
It is made out of multidimensional arrays.
We referred to it as an array of arrays.
Consider the following example:
* The outer array is [2][3]bytes in size, with each element being an inside array.
* [3]btye is the value of the inner array.
sum := byte(0)
cost := [2][3]byte{
{1, 2, 3},
{4, 5, 6},
}
for _, outer := range cost {
for _, inner := range outer {
sum += inner
}
}
fmt.Println(sum)
Get rid of the magic number
Take a look of this example below.
Ex:
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[pass|fail]")
return
}
mode := args[0]
moods := [...][3]string{
{
"happy", "good", "nice",
},
{
"sad", "bad", "terrible",
},
}
rand.Seed(time.Now().UnixNano())
n := rand.Intn(len(moods))
switch mode {
case "positive":
fmt.Printf("%s\n", moods[0][n])
case "negative":
fmt.Printf("%s\n", moods[1][n])
}
We found that there are two magic numbers in our program.
In our program, we discovered two magical numbers.
We should avoid utilizing magic numbers in best practice.
We can leverage Go's Keyed Element capability.
The index positions are described by keyed elements.
Each key corresponds to an array index.
args := os.Args[1:]
if len(args) != 1 {
fmt.Println("[pass|fail]")
return
}
mode := args[0]
moods := [...][3]string{
{
"happy", "good", "nice",
},
{
"sad", "bad", "terrible",
},
}
const (
pass = iota
fail
)
rand.Seed(time.Now().UnixNano())
n := rand.Intn(len(moods))
switch mode {
case "positive":
fmt.Printf("%s\n", moods[0][n])
case "negative":
fmt.Printf("%s\n", moods[fail][n])
}
No comments:
Post a Comment