继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

学Go语言:循环与条件判断教学

缥缈止盈
关注TA
已关注
手记 326
粉丝 36
获赞 158

让我们继续我们的 Go 旅程。上次,我们在 WSL 中安装并配置好了 Go,并介绍了值、变量和常量等基础知识。这次,我们将深入探讨 Go 中的 for 循环和条件判断,它们是 Go 语言中决策和循环的基础。如果你想跟着一起学习,可以参考 Go by Example 中的 for 循环部分。

一只穿着滑板的戈弗

在本文的最后,我们还将快速地介绍一下如何使用简单的 DockerfileDocker 中运行 Go 程序,让它们易于打包并可以在任何地方运行。

循环

在讨论for循环时,通常直接说“循环”更简洁,但在技术文档中保留for有助于保持术语的一致性。

我们的第一个重点是简单的 for 循环语句。这里举的例子有几种不同的循环,我们来挨个看看。

i := 1
for i <= 3 {
    println(i)
    i = i + 1
}

// 这是一个简单的循环,我们从1开始打印到3。

全屏模式 退出全屏

我们首先在一个循环之外,用 := 语法声明并赋值一个名为 i 的变量,并将其初始化为 1。在每次循环时打印当前的 i 值,并将 i1。当 i 达到 4 时,循环结束。

虽然在循环外面声明 i 是可以工作的,但在初始化时在循环内部声明它更常见,也更清晰。在循环开始时声明它更常见且更清晰。

// 下面的代码是一个简单的for循环,它会打印从0到2的数字。
for j := 0; j < 3; j++ {
    fmt.Println(j)
}

切换到全屏,退出全屏

这个第二个循环更接近我期望的样子。变量 j 在循环内部被声明,初始值是 0,每次迭代后增加,直到 j 达到 3 时停止。每次迭代都会打印 j 的当前值。

下面的代码是一个Go语言的例子,它使用`for`循环遍历数字范围0到2,并打印每个数字。

切换到全屏 / 退出全屏

这个循环迭代3次,i 的值分别为0、1和2。这与之前的循环实质上是一样的,只不过写得更简洁和标准。这是一个范围型循环,后续我们还会看到这种语法用于数组和切片。

以下是一个简单的 Go 代码片段,它会打印 'loop' 并立即退出循环。

    for {
        fmt.Println("loop")
        break
    }

切换到全屏 / 退出全屏

事情现在开始变得有趣了。这个循环没有设置停止条件,所以它会一直运行下去,不过我们在Println之后立即使用break终止它。这在你需要在任何时候根据条件退出循环时很有用。

这段代码是用来遍历一个范围从0到5的数字,如果数字是偶数,则跳过它,如果是奇数,则打印出来。

全屏模式 退出全屏

这里有个狡猾的例子。我们看到了多个新事物;包括着取模运算符(%),我们的第一个if条件判断,以及continue语句。

这个循环从 0 数到 5,包括 05。它利用 n % 2 == 0 判断 n 是否为偶数。如果是,则 continue 会跳过当前循环的其余部分,然后继续到下一个数字。否则,打印 n

简单来说,它只打印出范围内的奇数(即奇数)。

条件判断

条件语句在任何编程语言中都是必不可少的,它们让我们可以根据输入变量来决定程序的分支流程。主要有两种类型的条件语句:if/else 语句和 switch 语句,让我们来了解一下它们。

if/else 语句

if 语句其实判断一个表达式,该表达式的结果要么是 true,要么是 false。如果表达式结果为 true,就做某事;如果结果为 false,则做另一件事。

再来看这个例子,我们一个一个地审视这些陈述。

    如果 7 % 2 == 0 {
        fmt.Println("7 是偶数。")
    } else {
        fmt.Println("7 是奇数。")
    }

点击进入全屏模式 点击退出全屏

我们的老朋友,取模操作符,又来了。在下面这个例子中,我们检查7是否为偶数(不是),并打印出结果(它确实不是)。

    if 8%4 == 0 {
        fmt.Println("4 可以整除 8")
    }

切换到全屏 / 退出全屏

这基本上和前面的例子一样,这说明else部分不是必须的。

    if 8%2 == 0 || 7%2 == 0 {
        fmt.Println("8和7中有一个是偶数")
    }

点击全屏模式 点击退出全屏

这里我们有一个 条件,如果你用过其他语言,这应该看起来很熟悉,让 if 语句在任一条件为真时执行

    if num := 9; num < 0 {
        fmt.Println(num, "是负数")
    } else if num < 10 {
        fmt.Println(num, "是一位数")
    } else {
        fmt.Println(num, "是多位数")
    }

按全屏 按退出全屏

最后我们这里有一个 else if 示例。这允许我们对输入进行多个条件检查,并执行第一个为真的条件。末尾的 else 可以捕获所有未通过其他条件的任何情况。需要注意的是,变量 num 的作用域仅限于这个 if/else 块。

我不太喜欢这种在if语句里声明变量的方法。这种方式读起来不太舒服。我们可以重写他们的例子,使其更易读,来避免这种写法。

    num := 9

    if num < 0 {
        fmt.Println(num, "是负的")
    } else if num < 10 {
        fmt.Println(num, "是个一位数")
    } else {
        fmt.Println(num, "是多位的")
    }

全屏显示 退出全屏

Go 没有 三元操作符,如果你习惯了其他语言中的三元操作符,这可能让你感到遗憾,但让我们看看我们是否真的会错过它。

开关语句(switch语句)

虽然 switch 语句类似于 if/else 块,但还是有些不同。它也依赖于评估表达式的值。但这些表达式不仅可以是 truefalse,还可以是任何值,并且我们还可以为每种结果设置一个 case,并且还有一个 default 情况来捕获其他所有情况。

我们把这个例子拆开来看看,看看他们是不是偷偷加了什么新东西吧。

    i := 2
    fmt.Print("写 ", i, " 为 ")
    switch i {
    case 1:
        fmt.Println("一")
    case 2:
        fmt.Println("二")
    case 3:
        fmt.Println("三")
    default:
        fmt.Println("其他数字")
    }

点击这里全屏模式,点击这里退出全屏

首先举一个例子,已经加入了一些新东西。fmt 里的 Print 在打印时不会自动换行,我们可以用逗号分隔值,把它们拼接起来。

除了这个例子比较简单以外,定义变量 i,判断 i 是否为 1、2 或 3,如果是则打印出相应的单词。

    switch 根据今天是星期几 {
    case time.Saturday, time.Sunday:
        fmt.Println("今天是星期六或星期日")
    default:
        fmt.Println("今天是工作日,不是周末")
    }

进入全屏,退出全屏

在这里,我们第一次看到time包。看起来我们在使用enum,但因为还没学到相关内容,只能先搁置了。我们只需要知道,我们的表达式获取了当前是星期几,并使用了case,用逗号分隔来像or运算符那样起作用,我们检查是否是周末或平时工作日。

    t := time.Now()
    switch {
    case t.Hour() < 12:
        fmt.Println("现在还不到中午")
    default:
        fmt.Println("现在已经过了中午")
    }

全屏模式切换 退出全屏

这个例子与之前的例子类似,只是我们将 time.Now() 的调用结果存储为一个变量,并且没有将表达式传递给 switch。这将条件检查移至各个 case 语句中,使其行为类似于 if/else 语句的行为,其中第一个为 true 的 case 将被执行。

    whatAmI := func(i interface{}) {
        switch t := i.(type) {
        case bool:
            fmt.Println("我是一个布尔值")
        case int:
            fmt.Println("我是一个整数")
        default:
            fmt.Printf("不知道这是什么类型 %T\n", t)
        }
    }

    whatAmI(true)
    whatAmI(1)
    whatAmI("嘿")

全屏 | 退出全屏

好的,我猜他们可能会偷偷加入一些额外的东西,果然如此,这里就有了我们第一个可重用的函数,一个叫接口的东西(这个我也不太清楚)和一个Printf函数。

让我们一步步来,弄清楚这是在说啥。首先,我们有一个叫做 whatAmI 的函数,它接受一个 interface{} 类型的参数 i

我不太清楚interface{}是什么意思,所以我快速查了一下。看起来interface是我们稍后会学到的内容,但interface{}是用来告诉Go我们不知道传递给函数的是什么类型。可以把interface{}想象成一个占位符,它可以容纳任何类型的数据。也就是说,i可以是任何东西。

接下来是我们的 switch 表达式,我们声明了一个新的变量 t 并让它存储 i 的类型。这使我们可以根据需要的类型来编写 case

我们有两个case和一个default备用。前两个case分别检查i是否为booltruefalse)或是否为int(整数),如果不是这两种情况,备用会使用Printf输出其类型。Printf允许格式化输出,其中%T会打印变量的类型。我们在这里使用Printf是因为%T不能直接转换为字符串。我们还需要以\n结尾来添加换行符。

Docker容器

运行 Go 应用程序的一个好方法是将其 打包成 Docker 镜像,这使得它们可以在包括 Windows、Linux 和 macOS 在内的不同系统上轻松移植。我们将使用 多阶段 Dockerfile 来高效构建和运行我们的 Go 程序。

Docker标志(点击以查看Docker标志)

为什么使用多阶段构建的Dockerfile?

多阶段构建能帮助我们使最终镜像更小更高效,通过将构建环境与运行时环境分离开来。这减少不必要的依赖项,让最终镜像更干净,从而提升安全性和性能。

让我们先写一个 Dockerfile

    # 构建 GO 二进制程序
    FROM golang:1.24.1-alpine AS build
    COPY ./main.go ./main.go
    RUN go build -o /bin/output ./main.go

    # 运行 GO 二进制程序
    FROM scratch:
    COPY --from=build /bin/output /bin/output
    CMD ["/bin/output"]

    # 构建阶段:从 Alpine 版本的 Go 1.24.1 开始

进入全屏,退出全屏

构建步骤

我们从官方的golang:1.24.1-alpine镜像起步。我们将main.go文件复制到容器里(你可以重命名这个文件,如果需要的话),然后将其编译成可执行文件并放置在/bin/output

运行时

运行时阶段使用 FROM scratch,这意味着它没有任何基础操作系统。scratch 是一个空的镜像,不包含任何其他内容。这将最小化最终镜像的大小。我们使用 COPY --from=build 命令,该命令仅从构建阶段高效复制编译后的二进制文件,并将 CMD 设置为 ["/bin/output"] 作为入口命令。

构建并运行Docker容器

要构建并运行该镜像,可以使用以下命令:

请注意在命令前加上适当的提示符号,如“$”或“>”。

# 构建镜像(比如使用 `docker build` 命令,`.` 表示当前目录)
docker build -t my-go-app:latest .

# 运行容器(比如使用 `docker run` 命令)
docker run my-go-app:latest

全屏 退出全屏

结束啦

这次我们已经涵盖了非常多的内容,我们的程序正变得越来越高级。我们正在顺利地前进,而且语法使用起来非常简单。下次我们将看看数组、切片和映射。我们确实取得了一些进展,但是,但我们才刚刚开始了解皮毛。

感谢阅读!如果你想跟我联系,这里有我的TwitterBlueSky,和LinkedIn。来打个招呼哦 😊

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP