跳转到主要内容

【Go语言开发】如何在 Go 中构造 for 循环?

介绍


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

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

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

【Go语言开发】在 Go 中处理循环时使用 Break 和 Continue 语句

介绍


在 Go 中使用 for 循环可以让您以有效的方式自动化和重复任务。

学习如何控制循环的操作和流程将允许在您的程序中自定义逻辑。 您可以使用 break 和 continue 语句控制循环。

中断语句(break)


在 Go 中,break 语句终止当前循环的执行。 中断几乎总是与条件 if 语句配对。

让我们看一个在 for 循环中使用 break 语句的示例:

package main

import "fmt"

func main() {
    for i := 0; i < 10; i++ {
        if i == 5 {
            fmt.Println("Breaking out of loop")
            break // break here
        }
        fmt.Println("The value of i is", i)
    }
    fmt.Println("Exiting program")
}

这个小程序创建了一个 for 循环,该循环将在 i 小于 10 时进行迭代。

【Go语言开发】在 Go 中处理恐慌(Panics )

介绍


程序遇到的错误分为两大类:程序员已经预料到的错误和程序员没有预料到的错误。我们在前两篇关于错误处理的文章中介绍的错误接口主要处理我们在编写 Go 程序时所期望的错误。错误接口甚至允许我们确认函数调用发生错误的罕见可能性,因此我们可以在这些情况下做出适当的响应。

恐慌属于第二类错误,这是程序员没有预料到的。这些不可预见的错误导致程序自发终止并退出正在运行的 Go 程序。常见的错误通常是造成恐慌的原因。在本教程中,我们将研究常见操作在 Go 中产生恐慌的几种方式,我们还将看到避免这些恐慌的方法。我们还将使用 defer 语句和恢复函数来捕获恐慌,以免它们有机会意外终止我们正在运行的 Go 程序。

了解恐慌(Panics )


Go 中有某些操作会自动返回恐慌并停止程序。常见操作包括索引超出其容量的数组、执行类型断言、在 nil 指针上调用方法、错误地使用互斥锁以及尝试使用封闭通道。大多数这些情况是由于在编译程序时编译器无法检测到的编程错误造成的。

由于恐慌包含有助于解决问题的细节,因此开发人员通常使用恐慌来表示他们在程序开发过程中犯了错误。

【Go语言开发】如何在 Go 中编写包(Packages )

介绍

一个包由位于同一目录中的 Go 文件组成,并且在开头具有相同的包语句。您可以从包中包含其他功能,以使您的程序更加复杂。一些包可通过 Go 标准库获得,因此随 Go 安装一起安装。其他的可以用 Go 的 go get 命令安装。您还可以通过使用必要的包语句在要共享代码的同一目录中创建 Go 文件来构建自己的 Go 包。

本教程将指导您编写 Go 包以在其他编程文件中使用。

先决条件

 

  • 按照如何安装和设置 Go 系列的本地编程环境中的教程之一设置 Go 编程环境。按照本地编程环境教程中的第 5 步创建您的 Go 工作区。要遵循本文中的示例和命名约定,请阅读第一部分编写和导入包。
  • 要加深您对 GOPATH 的了解,请阅读我们的文章了解 GOPATH。


编写和导入包


编写一个包就像编写任何其他 Go 文件一样。包可以包含函数、类型和变量的定义,然后可以在其他 Go 程序中使用。

【Go语言开发】了解 Go 中的包的可见性

介绍


在 Go 中创建包时,最终目标通常是使包可供其他开发人员使用,无论是高阶包还是整个程序。通过导入包,您的代码可以作为其他更复杂工具的构建块。但是,只有某些包可用于导入。这是由包的可见性决定的。

在此上下文中的可见性意味着可以引用包或其他构造的文件空间。例如,如果我们在函数中定义一个变量,该变量的可见性(范围)仅在定义它的函数内。同样,如果您在包中定义变量,则可以使其仅对该包可见,或者也允许它在包外可见。

在编写符合人体工程学的代码时,仔细控制包的可见性很重要,尤其是在考虑到您可能希望对包进行的未来更改时。如果您需要修复错误、提高性能或更改功能,您需要以不会破坏任何使用您的包的人的代码的方式进行更改。最小化重大更改的一种方法是只允许访问包中正确使用它所需的部分。通过限制访问,您可以在内部对您的包进行更改,而不会影响其他开发人员如何使用您的包。

在本文中,您将学习如何控制包的可见性,以及如何保护只应在包内使用的部分代码。为此,我们将创建一个基本的记录器来记录和调试消息,使用具有不同程度项目可见性的包。

先决条件


要遵循本文中的示例,您将需要:

【Go语言开发】理解 Go 中的延迟(defer )

介绍


Go 有许多其他编程语言中常见的控制流关键字,例如 if、switch、for 等。大多数其他编程语言中没有的一个关键字是 defer,虽然它不太常见,但您很快就会看到它在您的程序中有多大用处。

defer 语句的主要用途之一是清理资源,例如打开的文件、网络连接和数据库句柄。当您的程序使用完这些资源后,关闭它们以避免耗尽程序的限制并允许其他程序访问这些资源非常重要。 defer 通过将关闭文件/资源​​的调用保持在打开调用附近,使我们的代码更清晰,更不容易出错。

在本文中,我们将学习如何正确使用 defer 语句来清理资源以及使用 defer 时常犯的几个错误。

什么是延迟(defer )声明


defer 语句将 defer 关键字后面的函数调用添加到堆栈中。当添加它们的函数返回时,调用该堆栈上的所有调用。因为调用被放置在堆栈上,所以它们以后进先出的顺序被调用。

让我们通过打印一些文本来看看 defer 是如何工作的:

main.go

【Go语言基础】理解 Go 中的 init

介绍


在 Go 中,预定义的 init() 函数会启动一段代码,以便在包的任何其他部分之前运行。此代码将在导入包后立即执行,并且可以在您需要应用程序在特定状态下初始化时使用,例如当您具有特定配置或应用程序需要启动的一组资源时。导入副作用时也使用它,这是一种通过导入特定包来设置程序状态的技术。这通常用于将一个包注册到另一个包,以确保程序正在考虑任务的正确代码。

尽管 init() 是一个有用的工具,但它有时会使代码难以阅读,因为难以找到的 init() 实例会极大地影响代码的运行顺序。因此,对于刚接触 Go 的开发人员来说,了解这个函数的各个方面非常重要,这样他们才能确保在编写代码时以清晰的方式使用 init()。

在本教程中,您将了解如何使用 init() 来设置和初始化特定包变量、一次计算以及注册一个包以与另一个包一起使用。

先决条件


对于本文中的一些示例,您将需要:

【Go语言高级开发】理解 Go 中的指针

介绍


当你用 Go 编写软件时,你将编写函数和方法。您将数据作为参数传递给这些函数。有时,该函数需要数据的本地副本,而您希望原始数据保持不变。例如,如果您是一家银行,并且您有一个功能可以根据用户选择的储蓄计划向用户显示他们的余额变化,那么您不希望在客户选择计划之前更改他们的实际余额;您只想在计算中使用它。这称为按值传递,因为您将变量的值发送给函数,而不是变量本身。

其他时候,您可能希望函数能够更改原始变量中的数据。例如,当银行客户向他们的账户存款时,您希望存款功能能够访问实际余额,而不是副本。在这种情况下,您不需要将实际数据发送给函数;你只需要告诉函数数据在内存中的位置。称为指针的数据类型保存数据的内存地址,但不保存数据本身。内存地址告诉函数在哪里找到数据,而不是数据的值。您可以将指针传递给函数而不是数据,然后函数可以就地更改原始变量。这被称为通过引用传递,因为变量的值并没有传递给函数,只是它的位置。

在本文中,您将创建和使用指针来共享对变量内存空间的访问。

【Go语言开发】如何在 Go 中为错误添加额外信息

介绍


当 Go 中的函数失败时,该函数将使用错误接口返回一个值,以允许调用者处理该失败。在很多情况下,开发者会使用 fmt 包中的 fmt.Errorf 函数来返回这些值。但是,在 Go 1.13 之前,使用此函数的一个缺点是您会丢失有关可能导致返回错误的任何错误的信息。为了解决这个问题,开发人员要么使用包来提供一种将错误“包装”在其他错误中的方法,要么通过在他们的一种结构错误类型上实现 Error() 字符串方法来创建自定义错误。但是,如果您有许多不需要由调用者显式处理的错误,有时创建这些结构类型可能会很乏味,因此在 Go 1.13 中,该语言添加了一些功能以更容易处理这些情况。

一项功能是能够使用 fmt.Errorf 函数包装错误,该函数具有一个错误值,该错误值可以在以后解包以访问已包装的错误。这将错误包装功能构建到 Go 标准库中,因此不再需要使用第三方库。

此外,函数 errors.Is 和 errors.As 可以更容易地确定特定错误是否包含在给定错误中的任何位置,并且还可以让您直接访问该特定错误,而无需自己解开所有错误。

在本教程中,您将创建一个程序,该程序使用这些函数在从函数返回的错误中包含附加信息,然后创建您自己的支持包装和展开功能的自定义错误结构。

【Go语言开发】如何在 Go 中使用上下文

介绍


在开发大型应用程序时,尤其是在服务器软件中,有时除了函数独立运行所需的信息之外,了解更多关于它正在执行的环境的信息是有帮助的。例如,如果 Web 服务器函数正在处理特定客户端的 HTTP 请求,则该函数可能只需要知道客户端请求哪个 URL 来提供响应。该函数可能只将该 URL 作为参数。但是,在提供响应时总是会发生一些事情,例如客户端在收到响应之前断开连接。如果提供响应的函数不知道客户端已断开连接,则服务器软件最终可能会花费比计算永远不会使用的响应所需的更多计算时间。

在这种情况下,了解请求的上下文,例如客户端的连接状态,允许服务器在客户端断开连接后停止处理请求。这可以在繁忙的服务器上节省宝贵的计算资源,并释放它们来处理另一个客户端的请求。这种类型的信息在函数执行需要时间的其他上下文中也很有帮助,例如进行数据库调用。为了使对此类信息的普遍访问成为可能,Go 在其标准库中包含了一个上下文包。

在本教程中,您将首先创建一个在函数中使用上下文的 Go 程序。然后,您将更新该程序以在上下文中存储附加数据并从另一个函数中检索它。最后,您将使用上下文的能力来表示它已完成以停止处理其他数据。

先决条件