golang for循环_如何在Go中构造For循环

本文详细介绍了Go语言中的循环结构,特别是如何使用ForClause、Condition和RangeClause创建循环。Go只有一种for循环,这使得代码更清晰易读。通过实例展示了如何遍历顺序数据类型、使用嵌套循环,并探讨了不同循环变体的用法,帮助开发者更好地理解和应用Go中的循环控制。
摘要由CSDN通过智能技术生成

golang for循环

介绍 (Introduction)

In computer programming, a loop is a code structure that loops around to repeatedly execute a piece of code, often until some condition is met. Using loops in computer programming allows you to automate and repeat similar tasks multiple times. Imagine if you had a list of files that you needed to process, or if you wanted to count the number of lines in an article. You would use a loop in your code to solve these types of problems.

在计算机编程中, 循环是一种代码结构,该结构不断循环执行以重复执行一段代码,直到满足某些条件为止。 在计算机编程中使用循环可让您多次自动执行和重复类似的任务。 想象一下,如果您有一个需要处理的文件列表,或者想计算一篇文章中的行数。 您可以在代码中使用循环来解决这些类型的问题。

In Go, a for loop implements the repeated execution of code based on a loop counter or loop variable. Unlike other programming languages that have multiple looping constructs such as while, do, etc., Go only has the for loop. This serves to make your code clearer and more readable, since you do not have to worry with multiple strategies to achieve the same looping construct. This enhanced readability and decreased cognitive load during development will also make your code less prone to error than in other languages.

在Go中, for循环根据循环计数器或循环变量实现代码的重复执行。 与其他具有多种循环结构(如whiledo等)的编程语言不同,Go仅具有for循环。 这使您的代码更清晰,更易读,因为您不必担心实现同一循环结构的多种策略。 与其他语言相比,这种增强的可读性和减少的开发过程中的认知负担也将使您的代码不易出错。

In this tutorial, you will learn how Go’s for loop works, including the three major variations of its use. We’ll start by showing how to create different types of for loops, followed by how to loop through sequential data types in Go. We’ll end by explaining how to use nested loops.

在本教程中,您将学习Go's for循环的工作原理,包括其用法的三个主要变化。 我们将首先展示如何创建不同类型的for循环,然后介绍如何在Go中循环遍历顺序数据类型 。 我们将在最后解释如何使用嵌套循环。

声明ForClause和条件循环 (Declaring ForClause and Condition Loops)

In order to account for a variety of use cases, there are three distinct ways to create for loops in Go, each with their own capabilities. These are to create a for loop with a Condition, a ForClause, or a RangeClause. In this section, we will explain how to declare and use the ForClause and Condition variants.

为了解决各种用例,有三种在Go中创建for循环的不同方法,每种方法都有自己的功能。 它们是使用ConditionForClauseRangeClause创建for循环的。 在本节中,我们将解释如何声明和使用ForClause和Condition变体。

Let’s look at how we can use a for loop with the ForClause first.

让我们先看看如何在ForClause中使用for循环。

A ForClause loop is defined as having an initial statement, followed by a condition, and then a post statement. These are arranged in the following syntax:

ForClause循环被定义为具有一个初始语句 ,一个条件 ,一个后语句 。 这些内容按以下语法排列:

for [ Initial Statement ] ; [ Condition ] ; [ Post Statement ] {
    [Action]
}

To explain what the preceding components do, let’s look at a for loop that increments through a specified range of values using the ForClause syntax:

为了解释上述组件的作用,我们来看一个for循环,该循环使用ForClause语法在指定的值范围内递增:

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

Let’s break this loop down and identify each part.

让我们打破这个循环,确定每个部分。

The first part of the loop is i := 0. This is the initial statement:

循环的第一部分是i := 0 。 这是最初的声明:

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

It states that we are declaring a variable called i, and setting the initial value to 0.

它声明我们正在声明一个名为i的变量,并将初始值设置为0

Next is the condition:

接下来是条件:

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

In this condition, we stated that while i is less than the value of 5, the loop should continue looping.

在这种情况下,我们表示虽然i小于5的值,但循环应继续循环。

Finally, we have the post statement:

最后,我们有post声明:

for i := 0; i < 5; i++ {
    fmt.Println(i)
}

In the post statement, we increment the loop variable i up by one each time an iteration occurs using the i++ increment operator.

在post语句中,每次使用i++ 增量运算符进行迭代时,我们将循环变量i 递增1

When we run this program, the output looks like this:

当我们运行该程序时,输出如下所示:


   
   
Output
0 1 2 3 4

The loop ran 5 times. Initially, it set i to 0, and then checked to see if i was less than 5. Since the value of i was less than 5, the loop executed and the action of fmt.Println(i) was executed. After the loop finished, the post statement of i++ was called, and the value of i was incremented by 1.

循环运行了5次。 最初,它将i设置为0 ,然后检查i是否小于5 。 由于i的值小于5 ,因此执行了循环并执行了fmt.Println(i)的操作。 循环结束后,将调用i++的post语句,并且i的值将增加1。

Note: Keep in mind that in programming we tend to begin at index 0, so that is why although 5 numbers are printed out, they range from 0-4.

注意:请记住,在编程中,我们倾向于从索引0开始,这就是为什么尽管打印出5个数字,但它们的范围是0-4。

We aren’t limited to starting at 0 or ending at a specified value. We can assign any value to our initial statement, and also stop at any value in our post statement. This allows us to create any desired range to loop through:

我们不限于从0开始或以指定值结束。 我们可以为初始语句分配任何值,也可以在post语句中停止任何值。 这使我们可以创建任何想要的范围以循环通过:

for i := 20; i < 25; i++ {
    fmt.Println(i)
}

Here, the iteration goes from 20 (inclusive) to 25 (exclusive), so the output looks like this:

在这里,迭代次数从20(含)增加到25(不含),因此输出如下所示:


   
   
Output
20 21 22 23 24

We can also use our post statement to increment at different values. This is similar to step in other languages:

我们还可以使用post语句以不同的值递增。 这类似于其他语言中的step

First, let’s use a post statement with a positive value:

首先,让我们使用具有正值的post语句:

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

In this case, the for loop is set up so that the numbers from 0 to 15 print out, but at an increment of 3, so that only every third number is printed, like so:

在这种情况下,将设置for循环,以便打印出从0到15的数字,但以3为增量,这样仅打印第三个数字,如下所示:


   
   
Output
0 3 6 9 12

We can also use a negative value for our post statement argument to iterate backwards, but we’ll have to adjust our initial statement and condition arguments accordingly:

我们还可以对post语句参数使用负值以向后迭代,但是我们必须相应地调整初始语句和条件参数:

for i := 100; i > 0; i -= 10 {
    fmt.Println(i)
}

Here, we set i to an initial value of 100, use the condition of i < 0 to stop at 0, and the post statement decrements the value by 10 with the -= operator. The loop begins at 100 and ends at 0, decreasing by 10 with each iteration. We can see this occur in the output:

这里,我们设置i到的初始值100 ,使用的条件i < 0停止在0 ,和后声明10与递减值-=运算符。 循环从100开始,在0结束,每次迭代减少10。 我们可以在输出中看到这种情况:


   
   
Output
100 90 80 70 60 50 40 30 20 10

You can also exclude the initial statement and the post statement from the for syntax, and only use the condition. This is what is known as a Condition loop:

您也可以从for语法中排除初始语句和post语句,仅使用条件。 这就是所谓的条件循环

i := 0
for i < 5 {
    fmt.Println(i)
    i++
}

This time, we declared the variable i separately from the for loop in the preceding line of code. The loop only has a condition clause that checks to see if i is less than 5. As long as the condition evaluates to true, the loop will continue to iterate.

这次,我们在代码的前一行中将变量ifor循环分开声明。 循环中只有一个条件子句,用于检查i是否小于5 。 只要条件评估为true ,循环就会继续进行迭代。

Sometimes you may not know the number of iterations you will need to complete a certain task. In that case, you can omit all statements, and use the break keyword to exit execution:

有时您可能不知道完成特定任务所需的迭代次数。 在这种情况下,您可以忽略所有语句,并使用break关键字退出执行:

for {
    if someCondition {
        break
    }
    // do action here
}

An example of this may be if we are reading from an indeterminately sized structure like a buffer and we don’t know when we will be done reading:

例如,如果我们正在从大小不确定的结构(如缓冲区)中读取数据,而我们不知道何时完成读取:

buffer.go
buffer.go
package main

import (
    "bytes"
    "fmt"
    "io"
)

func main() {
    buf := bytes.NewBufferString("one\ntwo\nthree\nfour\n")

    for {
        line, err := buf.ReadString('\n')
        if err != nil {
            if err == io.EOF {

                fmt.Print(line)
                break
            }
            fmt.Println(err)
            break
        }
        fmt.Print(line)
    }
}

In the preceding code, buf :=bytes.NewBufferString("one\ntwo\nthree\nfour\n") declares a buffer with some data. Because we don’t know when the buffer will finish reading, we create a for loop with no clause. Inside the for loop, we use line, err := buf.ReadString('\n') to read a line from the buffer and check to see if there was an error reading from the buffer. If there was, we address the error, and use the break keyword to exit the for loop. With these break points, you do not need to include a condition to stop the loop.

在前面的代码中, buf :=bytes.NewBufferString("one\ntwo\nthree\nfour\n")声明一个包含一些数据的缓冲区。 因为我们不知道缓冲区何时完成读取,所以我们创建了一个无子句的for循环。 在for循环内,我们使用line, err := buf.ReadString('\n')行从缓冲区读取一行,并检查是否从缓冲区读取错误。 如果存在,我们将解决错误,并使用break关键字退出for循环 。 使用这些break ,您无需包括条件即可停止循环。

In this section, we learned how to declare a ForClause loop and use it to iterate through a known range of values. We also learned how to use a Condition loop to iterate until a specific condition was met. Next, we’ll learn how the RangeClause is used for iterating through sequential data types.

在本节中,我们学习了如何声明ForClause循环并使用它循环遍历已知值范围。 我们还学习了如何使用条件循环进行迭代,直到满足特定条件为止。 接下来,我们将学习如何使用RangeClause遍历顺序数据类型。

使用RangeClause遍历顺序数据类型 (Looping Through Sequential Data Types with RangeClause)

It is common in Go to use for loops to iterate over the elements of sequential or collection data types like slices, arrays, and strings. To make it easier to do so, we can use a for loop with RangeClause syntax. While you can loop through sequential data types using the ForClause syntax, the RangeClause is cleaner and easier to read.

在Go中,常见的是使用for循环来迭代顺序或集合数据类型的元素,例如slice,arraystring 。 为了简化操作,我们可以使用带有RangeClause语法的for循环。 尽管可以使用ForClause语法遍历顺序数据类型,但RangeClause更加整洁且易于阅读。

Before we look at using the RangeClause, let’s look at how we can iterate through a slice by using the ForClause syntax:

在使用RangeClause之前,让我们看一下如何使用ForClause语法遍历切片:

main.go
main.go
package main

import "fmt"

func main() {
    sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

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

Running this will give the following output, printing out each element of the slice:

运行此命令将得到以下输出,打印出切片的每个元素:


   
   
Output
hammerhead great white dogfish frilled bullhead requiem

Now, let’s use the RangeClause to perform the same set of actions:

现在,让我们使用RangeClause来执行相同的一组操作:

main.go
main.go
package main

import "fmt"

func main() {
    sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

    for i, shark := range sharks {
        fmt.Println(i, shark)
    }
}

In this case, we are printing out each item in the list. Though we used the variables i and shark, we could have called the variable any other valid variable name and we would get the same output:

在这种情况下,我们将打印出列表中的每个项目。 尽管我们使用了变量ishark ,但我们可以将变量称为其他任何有效变量名,并且得到相同的输出:


   
   
Output
0 hammerhead 1 great white 2 dogfish 3 frilled 4 bullhead 5 requiem

When using range on a slice, it will always return two values. The first value will be the index that the current iteration of the loop is in, and the second is the value at that index. In this case, for the first iteration, the index was 0, and the value was hammerhead.

在切片上使用range时,它将始终返回两个值。 第一个值是循环当前迭代所在的索引,第二个值是该索引处的值。 在这种情况下,对于第一次迭代,索引为0 ,值是hammerhead

Sometimes, we only want the value inside the slice elements, not the index. If we change the preceding code to only print out the value however, we will receive a compile time error:

有时,我们只需要slice元素内的值,而不是索引。 但是,如果将前面的代码更改为仅打印出该值,则会收到编译时错误:

main.go
main.go
package main

import "fmt"

func main() {
    sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

    for i, shark := range sharks {
        fmt.Println(shark)
    }
}

   
   
Output
src/range-error.go:8:6: i declared and not used

Because i is declared in the for loop, but never used, the compiler will respond with the error of i declared and not used. This is the same error that you will receive in Go any time you declare a variable and don’t use it.

因为i是在for循环中声明的,但从未使用过,所以编译器将以i declared and not used的错误响应。 这是您在声明变量而不使用它时会在Go中收到的相同错误。

Because of this, Go has the blank identifier which is an underscore (_). In a for loop, you can use the blank identifier to ignore any value returned from the range keyword. In this case, we want to ignore the index, which is the first argument returned.

因此,Go的空白标识符为下划线( _ )。 在for循环中,可以使用空白标识符忽略range关键字返回的任何值。 在这种情况下,我们要忽略索引,它是返回的第一个参数。

main.go
main.go
package main

import "fmt"

func main() {
    sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

    for _, shark := range sharks {
        fmt.Println(shark)
    }
}

   
   
Output
hammerhead great white dogfish frilled bullhead requiem

This output shows that the for loop iterated through the slice of strings, and printed each item from the slice without the index.

此输出显示for循环遍历字符串切片,并在没有索引的情况下打印切片中的每个项目。

You can also use range to add items to a list:

您还可以使用range将项目添加到列表中:

main.go
main.go
package main

import "fmt"

func main() {
    sharks := []string{"hammerhead", "great white", "dogfish", "frilled", "bullhead", "requiem"}

    for range sharks {
        sharks = append(sharks, "shark")
    }

    fmt.Printf("%q\n", sharks)
}

   
   
Output
['hammerhead', 'great white', 'dogfish', 'frilled', 'bullhead', 'requiem', 'shark', 'shark', 'shark', 'shark', 'shark', 'shark']

Here, we have added a placeholder string of "shark" for each item of the length of the sharks slice.

在这里,我们为每条sharks片的长度添加了一个占位符字符串"shark"

Notice that we didn’t have to use the blank identifier _ to ignore any of the return values from the range operator. Go allows us to leave out the entire declaration portion of the range statement if we don’t need to use either of the return values.

注意,我们不必使用空白标识符_来忽略range运算符的任何返回值。 如果我们不需要使用任何一个返回值,Go允许我们省略range语句的整个声明部分。

We can also use the range operator to fill in values of a slice:

我们还可以使用range运算符来填充切片的值:

main.go
main.go
package main

import "fmt"

func main() {
    integers := make([]int, 10)
    fmt.Println(integers)

    for i := range integers {
        integers[i] = i
    }

    fmt.Println(integers)
}

In this example, the slice integers is initialized with ten empty values, but the for loop sets all the values in the list like so:

在此示例中,使用十个空值初始化切片integers ,但是for循环像这样设置列表中的所有值:


   
   
Output
[0 0 0 0 0 0 0 0 0 0] [0 1 2 3 4 5 6 7 8 9]

The first time we print the value of the slice integers, we see all zeros. Then we iterate through each index and set the value to the current index. Then when we print the value of integers a second time, showing that they all now have a value of 0 through 9.

第一次打印切片integers的值时,我们看到的都是零。 然后,我们遍历每个索引,并将值设置为当前索引。 然后,当我们打印的值integers第二次,表明他们现在都具有值09

We can also use the range operator to iterate through each character in a string:

我们还可以使用range运算符遍历字符串中的每个字符:

main.go
main.go
package main

import "fmt"

func main() {
    sammy := "Sammy"

    for _, letter := range sammy {
        fmt.Printf("%c\n", letter)
    }
}

   
   
Output
S a m m y

When iterating through a map, range will return both the key and the value:

遍历地图时range将同时返回

main.go
main.go
package main

import "fmt"

func main() {
    sammyShark := map[string]string{"name": "Sammy", "animal": "shark", "color": "blue", "location": "ocean"}

    for key, value := range sammyShark {
        fmt.Println(key + ": " + value)
    }
}

   
   
Output
color: blue location: ocean name: Sammy animal: shark

Note: It is important to note that the order in which a map returns is random. Each time you run this program you may get a different result.

注意:请务必注意,地图返回的顺序是随机的。 每次运行此程序,您可能会得到不同的结果。

Now that we have learned how to iterate over sequential data with range for loops, let’s look at how to use loops inside of loops.

现在,我们已经学会了如何与遍历序列数据range for循环,让我们来看看如何使用循环的内部循环。

嵌套循环 (Nested For Loops)

Loops can be nested in Go, as they can with other programming languages. Nesting is when we have one construct inside of another. In this case, a nested loop is a loop that occurs within another loop. These can be useful when you would like to have a looped action performed on every element of a data set.

循环可以嵌套在Go中,就像其他编程语言一样。 嵌套是当我们在一个内部包含一个构造时。 在这种情况下,嵌套循环是发生在另一个循环中的循环。 当您希望对数据集的每个元素执行循环操作时,这些功能很有用。

Nested loops are structurally similar to nested if statements. They are constructed like so:

嵌套循环在结构上类似于嵌套if语句 。 它们的构造如下:

for {
    [Action]
    for {
        [Action]  
    }
}

The program first encounters the outer loop, executing its first iteration. This first iteration triggers the inner, nested loop, which then runs to completion. Then the program returns back to the top of the outer loop, completing the second iteration and again triggering the nested loop. Again, the nested loop runs to completion, and the program returns back to the top of the outer loop until the sequence is complete or a break or other statement disrupts the process.

程序首先遇到外循环,执行其第一次迭代。 第一次迭代触发内部嵌套循环,然后运行完成。 然后,程序返回到外部循环的顶部,完成第二次迭代,并再次触发嵌套循环。 再次,嵌套循环运行完成,并且程序返回到外部循环的顶部,直到序列完成或中断或其他语句破坏了该过程。

Let’s implement a nested for loop so we can take a closer look. In this example, the outer loop will iterate through a slice of integers called numList, and the inner loop will iterate through a slice of strings called alphaList.

让我们实现一个嵌套的for循环,以便我们仔细看一下。 在此示例中,外循环将遍历一片称为numList的整数,而内循环将遍历一片称为alphaList的字符串。

main.go
main.go
package main

import "fmt"

func main() {
    numList := []int{1, 2, 3}
    alphaList := []string{"a", "b", "c"}

    for _, i := range numList {
        fmt.Println(i)
        for _, letter := range alphaList {
            fmt.Println(letter)
        }
    }
}

When we run this program, we’ll receive the following output:

运行此程序时,将收到以下输出:


   
   
Output
1 a b c 2 a b c 3 a b c

The output illustrates that the program completes the first iteration of the outer loop by printing 1, which then triggers completion of the inner loop, printing a, b, c consecutively. Once the inner loop has completed, the program returns to the top of the outer loop, prints 2, then again prints the inner loop in its entirety (a, b, c), etc.

输出说明该程序通过打印1完成外循环的第一次迭代,然后触发内循环的完成,依次打印abc 。 一旦内部循环完成,程序将返回到外部循环的顶部,打印2 ,然后再次完整地打印内部循环( abc ),等等。

Nested for loops can be useful for iterating through items within slices composed of slices. In a slice composed of slices, if we use just one for loop, the program will output each internal list as an item:

嵌套的for循环对于遍历由slice组成的slice中的项可能很有用。 在由切片组成的切片中,如果仅使用一个for循环,则程序会将每个内部列表作为一项输出:

main.go
main.go
package main

import "fmt"

func main() {
    ints := [][]int{
        []int{0, 1, 2},
        []int{-1, -2, -3},
        []int{9, 8, 7},
    }

    for _, i := range ints {
        fmt.Println(i)
    }
}

   
   
Output
[0 1 2] [-1 -2 -3] [9 8 7]

In order to access each individual item of the internal slices, we’ll implement a nested for loop:

为了访问内部切片的每个单独项,我们将实现一个嵌套的for循环:

main.go
main.go
package main

import "fmt"

func main() {
    ints := [][]int{
        []int{0, 1, 2},
        []int{-1, -2, -3},
        []int{9, 8, 7},
    }

    for _, i := range ints {
        for _, j := range i {
            fmt.Println(j)
        }
    }
}

   
   
Output
0 1 2 -1 -2 -3 9 8 7

When we use a nested for loop here, we are able to iterate over the individual items contained in the slices.

当我们在这里使用嵌套的for循环时,我们能够遍历切片中包含的各个项目。

结论 (Conclusion)

In this tutorial we learned how to declare and use for loops to solve for repetitive tasks in Go. We also learned the three different variations of a for loop and when to use them. To learn more about for loops and how to control the flow of them, read Using Break and Continue Statements When Working with Loops in Go.

在本教程中,我们学习了如何声明和使用for循环来解决Go中的重复任务。 我们还学习了for循环的三种不同变体以及何时使用它们。 要了解有关for循环以及如何控制它们的流程的更多信息,请阅读在Go中使用循环时使用Break和Continue语句

翻译自: https://www.digitalocean.com/community/tutorials/how-to-construct-for-loops-in-go

golang for循环

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值