Getting started with golang for loop
A loop in programming is a sequence of instructions that repeats itself until a certain condition is met. In this tutorial we will learn about Go For Loop through different data structures like structs, range , map, array, slice , string and channels and infinite loops. In Go, for loop is the only one contract for looping.
In this tutorial we will cover following scenarios using golang for loop:
- Looping through Maps
- Looping through slices.
- Looping through strings
- Looping through interface
- Looping through Channels
- Infinite loop
Syntax for using for loop in GO
In Go, this is what a for statement looks like:
for (init; condition; post) {
}
In Go, the for loop is the only construct for looping. The basic for loop in Go has the following components that are separated by semicolons.
- Init statement: Code that is executed be the first iteration
- Condition expression: checked/evaluated before every iteration
- Post statement: executed at the end of the iteration
The prerequisite to follow up with this article is to install Go runtime if you haven't already and create a main.go
file in your working directory.
Example
package main
import (
"fmt"
)
func main() {
total := 0
for i := 0; i < 10; i++ {
total += i
}
fmt.Println(total)
}
Output
$ go run main.go
45
Using golang for loop with struct
To loop through struct types in Go , makes use of the reflect
package. The Reflect package implements run-time reflection, hence allowing a program to modify objects with arbitrary types.
Example
package main
import (
"fmt"
"reflect"
)
type User struct {
FirstName string
Lastname string
Email string
Phone int
}
func main() {
u := User{
FirstName: "John",
Lastname: "Doe",
Email: "johndoe@gmail.com",
Phone: 1234567,
}
values := reflect.ValueOf(u)
typesOf := values.Type()
for i := 0; i < values.NumField(); i++ {
fmt.Printf("Field: %s\tValue: %v\n", typesOf.Field(i).Name, values.Field(i).Interface())
}
Explanation
In the above example, we define User struct
type with several attributes. In the main function, we then create an instance of the User struct. Unlike other types like Go maps that allow us to loop through keys and values on the fly, Go requires that you use the reflect package
in order to access the keys and values of a Go struct. We then initialize a variable named values
that holds the value from the user instance using reflect.ValueOf(u)
. The ValueOf
method returns a Value representing the run-time data. In the next line, use the call Type()
method on the values
run time data.In order to loop through all the keys and values in the user object, we get the number of key-value pairs from the user object using . Using for loop, we loop through the size of the values and access each key and value by calling typesOf.Field(i).Name
and values.Field(i).Interface()
respectively. typesOf.Field(i).Name
returns the keys names like FirstName
, LastName
, Email
and Phone
respectively while values.Field(i).Interface()
returns the respective values of the keys.
Output
$ go run main.go
Field: FirstName Value: John
Field: Lastname Value: Doe
Field: Email Value: johndoe@gmail.com
Field: Phone Value: 1234567
Using golang for loop with Maps
Go maps are one of the useful data structures and in computer science at large. It is made up of key and value where key can be any type that is comparable and a value that can be any type. Another map feature is that its unordered collection and it can order preserve the of the keys. We will loop through maps using the for-range type of Go for loop.
package main
import "fmt"
func main() {
user := map[string]interface{}{
"FirstName": "John Doe",
"LastName": "Doe",
"Country": "Go Land",
"Email": "johndoe@golinuxcloud.com",
}
for key, value := range user {
fmt.Printf("Key: %s === Value: %s \n", key, value)
}
}
Explanation
The range form of the for loop is used to iterate over maps and slices. When looping through the user map, two values are returned after every iteration. The first value is the key and the second value is the value for the respective key.
Output
$ go run main.go
Key: FirstName === Value: John Doe
Key: LastName === Value: Doe
Key: Country === Value: Go Land
Key: Email === Value: johndoe@golinuxcloud.com
Using golang for loop with slices
A slice in a Go is an array without a fixed size. It is important to note that a slice sits on a type of an array and therefore it does not store any data , rather it describes a section of an underlying array. To successfully loop through a Go slice, use the for range form of the Go for loop as shown below.
package main
import "fmt"
func main() {
nums := []int{1, 2, 3, 4, 5}
for index, value := range nums {
fmt.Printf("Position : %d == %d \n", index, value)
}
}
Output
$ go run main.go
Position : 0 == 1
Position : 1 == 2
Position : 2 == 3
Position : 3 == 4
Position : 4 == 5
Using golang for loop with strings
A string is a sequence of characters. For example “GolinuxCloud.com” is a string of characters . The Go for-range form loop can be used to loop through strings.
Example
package main
import "fmt"
func main() {
greetings := "Hello!"
for _, char := range greetings {
fmt.Printf("%c \n", char)
}
}
Explanation
Looping through a string in Go with the range keyword returns the index of each character and the respective unicode(char) integer of each character in the string.
Output
$ go run main.go
0 ==> 72
1 ==> 101
2 ==> 108
3 ==> 108
4 ==> 111
5 ==> 33
In order to print out the actual character values instead of unicode value, we can use fmt.Printf()
method from the fmt package
, that allows us to convert values from on type to another type, in our case, it will be from unicode to string.
Example
package main
import "fmt"
func main() {
greetings := "Hello!"
for _, char := range greetings {
fmt.Printf("==> %c \n", char)
}
}
Explanation
In the above example, we format our unicode integer in the loop from the previous example using %c
placeholder. We also used _
to indicate to the for loop body that we really don't care about the index value.
Output
$ go run main.go
==> H
==> e
==> l
==> l
==> o
==> !
Using golang for loop with interfaces
In Go every type implements an empty interface. An empty interface is an interface without any methods. Empty interfaces enables developers to create slices made up of different types as shown in example below.
Example
package main
import (
"fmt"
)
func main() {
items := []interface{}{1, "hello", 3.14}
for _, item := range items {
switch item.(type) {
case int:
fmt.Println("int")
case string:
fmt.Println("string")
case float64:
fmt.Println("float64")
default:
fmt.Println("unknown")
}
}
}
Explanation
In the preceding example, we create a slice of interface type and add values of type int
,string
and float
. We then use the for range
loop to loop through the items. We ignore the indexes of the values by using the underscore (_) to tell Go we do not really care about the index. Using a switch statement we check the type of each item in the slice and print a message on the terminal based on the type.
Output
$ go run main.go
int
string
float64
Using golang for loop with Channels
Channels are conduit pipes that connect concurrent goroutines. In Go, channels are typed pipes that developers can send and receive values using the <-
operator. The values in the channel flow in the direction the arrow points to. We can use a for loop with channels to repeatedly send values from the sender to the receiver. It is important to note that the sender of values can close a channel to indicate that no more values will be sent and this marks the end of the loop.
Therefore , using a range loop, the channel will receive values repeatedly until the channel is closed. It is only the sender that is allowed to close the channel and any attempt to send on a closed channel will result in a panic.
Example
package main
func testChannel(c chan string) {
users := []string{"user1", "user2", "user3", "user4", "user5"}
for _, user := range users {
c <- user
}
close(c)
}
func main() {
c := make(chan string, 10)
go testChannel(c)
for i := range c {
println(i)
}
}
Explanation
In the above example, we define a function called testChannel()
that takes a channel of type string as an argument. The testChannel()
function loops through an array of strings using the for range loop and sends the string to the channel. The operator <-
has been used to send messages in the direction of the channel. After all strings have been sent into the channel, the channel is closed. In the main function, we initialize a channel of type string. This channel will be used to pull string values from it. We then call testChannel()
to start sending string values into the channel. After filling the channel with string values , we use for range loop again to pull messages of the channel one after the other and print the string values in the terminal as shown in the below output.
Output
$ go run main.go
user1
user2
user3
user4
user5
Create and Infinite for loop
Go has an easy way of defining an infinite loop. In most cases we use infinite loops to run until an external intervention occurs. Please note that infinite loops do not have a stopping condition and therefore should always be used with a lot of care.
Example
package main
import (
"fmt"
"time"
)
func main() {
for {
fmt.Println("https://www.golinuxcloud.com is the best Go resource for learning Go")
time.Sleep(2 * time.Second)
}
}
Explanation
In the above code sample, the code will run indefinitely until we stop it by pressing ctrl + C on the keyboard as indicated in the output below.
Output
$ go run main.go
https://www.golinuxcloud.com is the best Go resource for learning Go
https://www.golinuxcloud.com is the best Go resource for learning Go
https://www.golinuxcloud.com is the best Go resource for learning Go
^Csignal: interrupt
Summary
In this article ,we learn about looping through different data structures like structs, strings, maps, slices and channels. Go struct is the only data structure that requires an extra package called reflect to be able to loop through both keys and values. The other data structures do not require any package to be able to loop through their items and attributes.
References
golang flow control
golang for loop