Go的循环语句

FOR循环

package main

import {
  "fmt"
  "os"
}

func main() {
  var s1,s2 string
  for i :=1, i < len(os.Args) ; i++ {  // 若改为 :=0 则输出的是被执行命令本身的名字即 Args[0]
    s1 += s2 + os.Args[i]
    s2 = " "
  }
  fmt.Println(s1)                     // 输出为空
}

Go的for循环的条件不需要加() 而{}强制添加

Go的循环因子不需要定义类型而是使用 := 初始值,程序执行时会自动匹配其类型

Go的os包以跨平台的方式,提供了一些与操作系统交互的函数和变量

Go的循环只有for循环一种,不过针对不同的循环因子分为不同的情况

os.Args[0] 输出的是被执行命令本身的名字

for initialization; condition; post {
    // zero or more statements
}

for循环三个部分不需括号包围。大括号强制要求,左大括号必须和post语句在同一行。

initialization(初始化)语句是可选的,在循环开始前执行。initalization如果存在,必须是一条简单语句(simple statement),即,短变量声明、自增语句、赋值语句或函数调用。condition(条件语句)是一个布尔表达式(boolean expression),其值在每次循环迭代开始时计算。如果为true则执行循环体语句。post语句在循环体执行结束后执行,之后再次对condition求值。condition值为false时,循环结束。

for循环的这三个部分每个都可以省略,如果省略 initialization 和 post,分号也可以省略:

// a traditional "while" loop
for condition {
    // ...
}
package main

import (
	"fmt"
)

func main() {
	sum := ""
	param := "a"
	for sum == "" {
		sum = param
		fmt.Println(sum)
	}
}

如果连condition也省略了,像下面这样:

// a traditional infinite loop
for {
    // ...
}

package main

import (
	"fmt"
)

func main() {
	sum := ""
	param := "a"
	for {
		sum = param
		fmt.Println(sum)
	}
}
这就变成一个无限循环,尽管如此,还可以用其他方式终止循环,如一条break或return语句。`

for循环的另一种形式,在某种数据类型的区间(range)上遍历,如字符串或切片。echo的第二版本展示了这种形式:

// Echo2 prints its command-line arguments.
package main

import (
    "fmt"
    "os"
)

func main() {
    s, sep := "", ""
    for _, arg := range os.Args[1:] {
        s += sep + arg
        sep = " "
    }
    fmt.Println(s)
}
每次循环迭代,range产生一对值:索引以及在该索引处的元素值。这个例子不需要索引,但range的语法要求,要处理元素,必须处理索引。一种思路是把索引赋值给一个临时变量(如temp)然后忽略它的值,但Go语言不允许使用无用的局部变量(local variables),因为这会导致编译错误。

package main

import (
	"fmt"
	"os"
)

func main() {
	sum, param := "", ""
	for _, arg := range os.Args[0:] {
		sum = param + arg
		fmt.Println(sum)
	}
}


Go语言中这种情况的解决方法是用空标识符(blank identifier),即_(也就是下划线)。空标识符可用于在任何语法需要变量名但程序逻辑不需要的时候(如:在循环里)丢弃不需要的循环索引,并保留元素值。大多数的Go程序员都会像上面这样使用range和_写echo程序,因为隐式地而非显式地索引os.Args,容易写对。

echo的这个版本使用一条短变量声明来声明并初始化s和seps,也可以将这两个变量分开声明

声明一个变量有好几种方式,下面这些都等价:

s := ""
var s string
var s = ""
var s string = ""
用哪种不用哪种,为什么呢?第一种形式,是一条短变量声明,最简洁,但只能用在函数内部,而不能用于包变量。第二种形式依赖于字符串的默认初始化零值机制,被初始化为""。第三种形式用得很少,除非同时声明多个变量。第四种形式显式地标明变量的类型,当变量类型与初值类型相同时,类型冗余,但如果两者类型不同,变量类型就必须了。
一般使用前两种形式中的某个,初始值重要的话就显式地指定变量的类型,否则使用隐式初始化。

如前文所述,每次循环迭代字符串s的内容都会更新。+=连接原字符串、空格和下个参数,产生新字符串,并把它赋值给s。s原来的内容已经不再使用,将在适当时机对它进行垃圾回收。

如果连接涉及的数据量很大,这种方式代价高昂。一种简单且高效的解决方案是使用strings包的Join函数:

func main() {
    fmt.Println(strings.Join(os.Args[1:], " "))
}
posted @ 2022-10-14 15:01  Kris_Chen  阅读(16)  评论(0)    收藏  举报