golang init_了解Go中的init

news/2024/7/4 23:02:18

golang init

介绍 (Introduction)

In Go, the predefined init() function sets off a piece of code to run before any other part of your package. This code will execute as soon as the package is imported, and can be used when you need your application to initialize in a specific state, such as when you have a specific configuration or set of resources with which your application needs to start. It is also used when importing a side effect, a technique used to set the state of a program by importing a specific package. This is often used to register one package with another to make sure that the program is considering the correct code for the task.

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

Although init() is a useful tool, it can sometimes make code difficult to read, since a hard-to-find init() instance will greatly affect the order in which the code is run. Because of this, it is important for developers who are new to Go to understand the facets of this function, so that they can make sure to use init() in a legible manner when writing code.

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

In this tutorial, you’ll learn how init() is used for the setup and initialization of specific package variables, one time computations, and the registration of a package for use with another package.

在本教程中,您将学习如何使用init()进行特定程序包变量的设置和初始化,一次计算以及为另一个程序包使用的程序包的注册。

先决条件 (Prerequisites)

For some of the examples in this article, you will need:

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

  • A Go workspace set up by following How To Install Go and Set Up a Local Programming Environment. This tutorial will use the following file structure:

    通过遵循如何安装Go和设置本地编程环境来设置 Go工作区。 本教程将使用以下文件结构:

.
├── bin 
│ 
└── src
    └── github.com
        └── gopherguides

声明init() (Declaring init())

Any time you declare an init() function, Go will load and run it prior to anything else in that package. To demonstrate this, this section will walk through how to define an init() function and show the effects on how the package runs.

每当您声明init()函数时,Go都会先加载并运行该程序,然后再运行该程序包中的其他任何程序。 为了证明这一点,本节将逐步介绍如何定义init()函数,并显示对程序包运行方式的影响。

Let’s first take the following as an example of code without the init() function:

首先让我们以不带init()函数的代码为例:

main.go
main.go
package main

import "fmt"

var weekday string

func main() {
    fmt.Printf("Today is %s", weekday)
}

In this program, we declared a global variable called weekday. By default, the value of weekday is an empty string.

在此程序中,我们声明了一个名为weekday的全局变量 。 默认情况下,“ weekday的值是一个空字符串。

Let’s run this code:

让我们运行以下代码:

  • go run main.go

    去运行main.go

Because the value of weekday is blank, when we run the program, we will get the following output:

由于weekday值为空白,因此在运行程序时,将获得以下输出:


   
Output
Today is

We can fill in the blank variable by introducing an init() function that initializes the value of weekday to the current day. Add in the following highlighted lines to main.go:

我们可以通过引入一个init()函数来填充空白变量,该函数将weekday的值初始化为当前日期。 将以下突出显示的行添加到main.go

main.go
main.go
package main

import (
    "fmt"
    "time"
)

var weekday string

func init() {
    weekday = time.Now().Weekday().String()
}

func main() {
    fmt.Printf("Today is %s", weekday)
}

In this code, we imported and used the time package to get the current day of the week (Now().Weekday().String()), then used init() to initialize weekday with that value.

在此代码中,我们导入并使用time包获取星期几( Now().Weekday().String() ),然后使用init()初始化具有该值的weekday

Now when we run the program, it will print out the current weekday:

现在,当我们运行该程序时,它将打印出当前工作日:


   
Output
Today is Monday

While this illustrates how init() works, a much more typical use case for init() is to use it when importing a package. This can be useful when you need to do specific setup tasks in a package before you want the package to be used. To demonstrate this, let’s create a program that will require a specific initialization for the package to work as intended.

虽然这说明了如何init()的作品,一个更加典型的使用情况init()是导入包时使用它。 当您需要在软件包中执行特定的安装任务之前,要使用该软件包,这将很有用。 为了演示这一点,让我们创建一个程序,该程序需要特定的初始化才能使程序包按预期工作。

初始化导入包 (Initializing Packages on Import)

First, we will write some code that selects a random creature from a slice and prints it out. However, we won’t use init() in our initial program. This will better show the problem we have, and how init() will solve our problem.

首先,我们将编写一些代码来从切片中选择一个随机生物并将其打印出来。 但是,我们不会在初始程序中使用init() 。 这将更好地显示我们遇到的问题,以及init()如何解决我们的问题。

From within your src/github.com/gopherguides/ directory, create a folder called creature with the following command:

src/github.com/gopherguides/目录中,使用以下命令创建一个名为creature的文件夹:

  • mkdir creature

    mkdir生物

Inside the creature folder, create a file called creature.go:

creature文件夹内,创建一个名为creature.go的文件:

  • nano creature/creature.go

    纳米生物/creature.go

In this file, add the following contents:

在此文件中,添加以下内容:

creature.go
生物
package creature

import (
    "math/rand"
)

var creatures = []string{"shark", "jellyfish", "squid", "octopus", "dolphin"}

func Random() string {
    i := rand.Intn(len(creatures))
    return creatures[i]
}

This file defines a variable called creatures that has a set of sea creatures initialized as values. It also has an exported Random function that will return a random value from the creatures variable.

该文件定义了一个名为creatures的变量,该变量具有一组初始化为值的海洋生物。 它还具有导出的 Random函数,该函数将从creatures变量返回一个随机值。

Save and quit this file.

保存并退出该文件。

Next, let’s create a cmd package that we will use to write our main() function and call the creature package.

接下来,让我们创建一个cmd包,该包将用于编写main()函数并调用creature包。

At the same file level from which we created the creature folder, create a cmd folder with the following command:

在我们创建creature文件夹的文件级别上,使用以下命令创建一个cmd文件夹:

  • mkdir cmd

    mkdir cmd

Inside the cmd folder, create a file called main.go:

cmd文件夹中,创建一个名为main.go的文件:

  • nano cmd/main.go

    纳米cmd / main.go

Add the following contents to the file:

将以下内容添加到文件中:

cmd/main.go
cmd / main.go
package main

import (
    "fmt"

    "github.com/gopherguides/creature"
)

func main() {
    fmt.Println(creature.Random())
    fmt.Println(creature.Random())
    fmt.Println(creature.Random())
    fmt.Println(creature.Random())
}

Here we imported the creature package, and then in the main() function, used the creature.Random() function to retrieve a random creature and print it out four times.

在这里,我们导入了creature包,然后在main()函数中,使用了creature.Random()函数来检索随机生物并将其打印四次。

Save and quit main.go.

保存并退出main.go

We now have our entire program written. However, before we can run this program, we’ll need to also create a couple of configuration files for our code to work properly. Go uses Go Modules to configure package dependencies for importing resources. These modules are configuration files placed in your package directory that tell the compiler where to import packages from. While learning about modules is beyond the scope of this article, we can write just a couple lines of configuration to make this example work locally.

现在,我们编写了整个程序。 但是,在运行该程序之前,我们还需要创建几个配置文件,以使我们的代码正常运行。 Go使用Go Modules配置用于导入资源的程序包依赖项。 这些模块是放置在软件包目录中的配置文件,用于告诉编译器从何处导入软件包。 尽管关于模块的学习超出了本文的范围,但我们仅需编写几行配置即可使该示例在本地运行。

In the cmd directory, create a file named go.mod:

cmd目录中,创建一个名为go.mod的文件:

  • nano cmd/go.mod

    纳米cmd / go.mod

Once the file is open, place in the following contents:

打开文件后,放置以下内容:

cmd/go.mod
cmd / go.mod
module github.com/gopherguides/cmd
 replace github.com/gopherguides/creature => ../creature

The first line of this file tells the compiler that the cmd package we created is in fact github.com/gopherguides/cmd. The second line tells the compiler that github.com/gopherguides/creature can be found locally on disk in the ../creature directory.

该文件的第一行告诉编译器,我们创建的cmd包实际上是github.com/gopherguides/cmd 。 第二行告诉编译器github.com/gopherguides/creature可以在本地和光盘中找到../creature目录。

Save and close the file. Next, create a go.mod file in the creature directory:

保存并关闭文件。 接下来,在creature目录中创建一个go.mod文件:

  • nano creature/go.mod

    纳米生物/go.mod

Add the following line of code to the file:

将以下代码行添加到文件中:

creature/go.mod
生物/go.mod
module github.com/gopherguides/creature

This tells the compiler that the creature package we created is actually the github.com/gopherguides/creature package. Without this, the cmd package would not know where to import this package from.

这告诉编译器我们创建的creature包实际上是github.com/gopherguides/creature包。 没有这个, cmd软件包将不知道从何处导入该软件包。

Save and quit the file.

保存并退出文件。

You should now have the following directory structure and file layout:

您现在应该具有以下目录结构和文件布局:

├── cmd
│   ├── go.mod
│   └── main.go
└── creature
    ├── go.mod
    └── creature.go

Now that we have all the configuration completed, we can run the main program with the following command:

现在我们已经完成了所有配置,我们可以使用以下命令运行main

  • go run cmd/main.go

    去运行cmd / main.go

This will give:

这将给出:


   
Output
jellyfish squid squid dolphin

When we ran this program, we received four values and printed them out. If we run the program multiple times, we will notice that we always get the same output, rather than a random result as expected. This is because the rand package creates pseudorandom numbers that will consistently generate the same output for a single initial state. To achieve a more random number, we can seed the package, or set a changing source so that the initial state is different every time we run the program. In Go, it is common to use the current time to seed the rand package.

当我们运行该程序时,我们收到了四个值并打印出来。 如果我们多次运行该程序,我们会注意到我们总是得到相同的输出,而不是预期的随机结果。 这是因为rand程序包会创建伪随机数,这些伪随机数将为单个初始状态一致地生成相同的输出。 为了获得更大的随机数,我们可以给程序包添加种子 ,或者设置一个变化的源,以便每次运行程序时初始状态都不同。 在Go中,通常使用当前时间来播种rand包。

Since we want the creature package to handle the random functionality, open up this file:

由于我们希望creature包处理随机功能,因此请打开以下文件:

  • nano creature/creature.go

    纳米生物/creature.go

Add the following highlighted lines to the creature.go file:

将以下突出显示的行添加到creature.go文件:

creature/creature.go
生物/creature.go
package creature

import (
    "math/rand"
    "time"
)

var creatures = []string{"shark", "jellyfish", "squid", "octopus", "dolphin"}

func Random() string {
    rand.Seed(time.Now().UnixNano())
    i := rand.Intn(len(creatures))
    return creatures[i]
}

In this code, we imported the time package and used Seed() to seed the current time. Save and exit the file.

在这段代码中,我们导入了time包,并使用Seed()播种当前时间。 保存并退出文件。

Now, when we run the program we will get a random result:

现在,当我们运行程序时,我们将得到一个随机结果:

  • go run cmd/main.go

    去运行cmd / main.go

   
Output
jellyfish octopus shark jellyfish

If you continue to run the program over and over, you will continue to get random results. However, this is not yet an ideal implementation of our code, because every time creature.Random() is called, it also re-seeds the rand package by calling rand.Seed(time.Now().UnixNano()) again. Re-seeding will increase the chance of seeding with the same initial value if the internal clock has not changed, which will cause possible repetitions of the random pattern, or will increase CPU processing time by having your program wait for the clock to change.

如果继续一遍又一遍地运行程序,则将继续获得随机结果。 然而,这还不是我们的代码的理想的实现,因为每次creature.Random()被调用时,它也重新种子rand通过调用封装rand.Seed(time.Now().UnixNano())一次。 如果内部时钟未更改,则重新播种将增加使用相同初始值进行播种的机会,这可能导致重复随机模式,或者通过让程序等待时钟更改来增加CPU处理时间。

To fix this, we can use an init() function. Let’s update the creature.go file:

为了解决这个问题,我们可以使用init()函数。 让我们更新creature.go文件。

  • nano creature/creature.go

    纳米生物/creature.go

Add the following lines of code:

添加以下代码行:

creature/creature.go
生物/creature.go
package creature

import (
    "math/rand"
    "time"
)

var creatures = []string{"shark", "jellyfish", "squid", "octopus", "dolphin"}

func init() {
    rand.Seed(time.Now().UnixNano())
}

func Random() string {
    i := rand.Intn(len(creatures))
    return creatures[i]
}

Adding the init() function tells the compiler that when the creature package is imported, it should run the init() function once, providing a single seed for the random number generation. This ensures that we don’t run code more than we have to. Now if we run the program, we will continue to get random results:

添加init()函数会告诉编译器,当导入creature包时,它应该运行一次init()函数,为生成随机数提供一个种子。 这样可以确保我们不会运行过多的代码。 现在,如果我们运行该程序,我们将继续获得随机结果:

  • go run cmd/main.go

    去运行cmd / main.go

   
Output
dolphin squid dolphin octopus

In this section, we have seen how using init() can ensure that the appropriate calculations or initializations are performed prior to the package being used. Next, we will see how to use multiple init() statements in a package.

在本节中,我们已经看到了使用init()如何确保在使用包之前执行适当的计算或初始化。 接下来,我们将看到如何在一个包中使用多个init()语句。

init()多个实例 (Multiple Instances of init())

Unlike the main() function that can only be declared once, the init() function can be declared multiple times throughout a package. However, multiple init()s can make it difficult to know which one has priority over the others. In this section, we will show how to maintain control over multiple init() statements.

main()函数只能声明一次不同, init()函数可以在整个包中声明多次。 但是,多个init()可能使得很难知道哪个优先于另一个。 在本节中,我们将展示如何保持对多个init()语句的控制。

In most cases, init() functions will execute in the order that you encounter them. Let’s take the following code as an example:

在大多数情况下, init()函数将按照您遇到它们的顺序执行。 让我们以以下代码为例:

main.go
main.go
package main

import "fmt"

func init() {
    fmt.Println("First init")
}

func init() {
    fmt.Println("Second init")
}

func init() {
    fmt.Println("Third init")
}

func init() {
    fmt.Println("Fourth init")
}

func main() {}

If we run the program with the following command:

如果我们使用以下命令运行程序:

  • go run main.go

    去运行main.go

We’ll receive the following output:

我们将收到以下输出:


   
Output
First init Second init Third init Fourth init

Notice that each init() is run in the order in which the compiler encounters it. However, it may not always be so easy to determine the order in which the init() function will be called.

请注意,每个init()编译器遇到它的顺序运行。 但是,确定init()函数的调用顺序可能并不总是那么容易。

Let’s look at a more complicated package structure in which we have multiple files each with their own init() function declared in them. To illustrate this, we will create a program that shares a variable called message and prints it out.

让我们看一个更复杂的包结构,其中我们有多个文件,每个文件中都声明了自己的init()函数。 为了说明这一点,我们将创建一个程序,该程序共享一个称为message的变量并将其打印出来。

Delete the creature and cmd directories and their contents from the earlier section, and replace them with the following directories and file structure:

从前面的部分删除creaturecmd目录及其内容,然后将其替换为以下目录和文件结构:

├── cmd
│   ├── a.go
│   ├── b.go
│   └── main.go
└── message
    └── message.go

Now let’s add the contents of each file. In a.go, add the following lines:

现在,让我们添加每个文件的内容。 在a.go ,添加以下行:

cmd/a.go
cmd / a.go
package main

import (
    "fmt"

    "github.com/gopherguides/message"
)

func init() {
    fmt.Println("a ->", message.Message)
}

This file contains a single init() function that prints out the value of message.Message from the message package.

该文件包含一个init()函数,该函数从message包中打印出message.Message的值。

Next, add the following contents to b.go:

接下来,将以下内容添加到b.go

cmd/b.go
cmd / b.go
package main

import (
    "fmt"

    "github.com/gopherguides/message"
)

func init() {
    message.Message = "Hello"
    fmt.Println("b ->", message.Message)
}

In b.go, we have a single init() function that set’s the value of message.Message to Hello and prints it out.

b.go ,我们有一个init()函数,用于将message.Message的值设置为Hello并将其打印出来。

Next, create main.go to look like the following:

接下来,创建main.go ,如下所示:

cmd/main.go
cmd / main.go
package main

func main() {}

This file does nothing, but provides an entry point for the program to run.

该文件不执行任何操作,但是为程序运行提供了一个入口点。

Finally, create your message.go file like the following:

最后,如下创建您的message.go文件:

message/message.go
message / message.go
package message

var Message string

Our message package declares the exported Message variable.

我们的message包声明了导出的Message变量。

To run the program, execute the following command from the cmd directory:

要运行该程序,请从cmd目录执行以下命令:

  • go run *.go

    去跑* .go

Because we have multiple Go files in the cmd folder that make up the main package, we need to tell the compiler that all the .go files in the cmd folder should be compiled. Using *.go tells the compiler to load all the files in the cmd folder that end in .go. If we issued the command of go run main.go, the program would fail to compile as it would not see the code in the a.go and b.go files.

因为在main包的cmd文件夹中有多个Go文件,所以我们需要告诉编译器cmd文件夹中的所有.go文件都应编译。 使用*.go告诉编译器加载以.go结尾的cmd文件夹中的所有文件。 如果我们发出go run main.go的命令,则该程序将无法编译,因为它将看不到a.gob.go文件中的代码。

This will give the following output:

这将给出以下输出:


   
Output
a -> b -> Hello

Per the Go language specification for Package Initialization, when multiple files are encountered in a package, they are processed alphabetically. Because of this, the first time we printed out message.Message from a.go, the value was blank. The value wasn’t initialized until the init() function from b.go had been run.

根据Go语言规范中的Package Initialization的规定 ,当一个包中遇到多个文件时,将按字母顺序处理它们。 因此,我们第一次打印出来自a.go message.Message时,该值为空白。 在运行b.goinit()函数之前,不会初始化该值。

If we were to change the file name of a.go to c.go, we would get a different result:

如果将c.go的文件名a.goc.go ,则会得到不同的结果:


   
Output
b -> Hello a -> Hello

Now the compiler encounters b.go first, and as such, the value of message.Message is already initialized with Hello when the init() function in c.go is encountered.

现在,编译器遇到b.go第一,正因为如此,价值message.Message已经与初始化Hello的时候init()函数c.go遇到。

This behavior could create a possible problem in your code. It is common in software development to change file names, and because of how init() is processed, changing file names may change the order in which init() is processed. This could have the undesired effect of changing your program’s output. To ensure reproducible initialization behavior, build systems are encouraged to present multiple files belonging to the same package in lexical file name order to a compiler. One way to ensure that all init() functions are loaded in order is to declare them all in one file. This will prevent the order from changing even if file names are changed.

此行为可能在您的代码中创建一个可能的问题。 在软件开发中,通常会更改文件名,并且由于init()的处理方式,更改文件名可能会更改init()的处理顺序。 这可能具有更改程序输出的不良影响。 为了确保可重现的初始化行为,鼓励构建系统以词法文件名的顺序向编译器提供属于同一软件包的多个文件。 确保依次加载所有init()函数的一种方法是在一个文件中声明它们。 即使文件名被更改,这也将防止顺序更改。

In addition to ensuring the order of your init() functions does not change, you should also try to avoid managing state in your package by using global variables, i.e., variables that are accessible from anywhere in the package. In the preceding program, the message.Message variable was available to the entire package and maintained the state of the program. Because of this access, the init() statements were able to change the variable and destablize the predictability of your program. To avoid this, try to work with variables in controlled spaces that have as little access as possible while still allowing the program to work.

除了确保init()函数的顺序不变之外,您还应尝试通过使用全局变量 (即,可从包中任何位置访问的变量)来避免管理包中的状态。 在前面的程序中, message.Message变量可用于整个程序包,并保持程序的状态。 由于具有这种访问权限, init()语句能够更改变量并破坏程序的可预测性。 为避免这种情况,请尝试在具有尽可能少访问权限的受控空间中使用变量,同时仍允许程序运行。

We have seen that you can have multiple init() declarations in a single package. However, doing so may create undesired effects and make your program hard to read or predict. Avoiding multiple init() statements or keeping them all in one file will ensure that the behavior of your program does not change when files are moved around or names are changed.

我们已经看到您可以在一个包中有多个init()声明。 但是,这样做可能会产生不良影响,并使程序难以阅读或预测。 避免使用多个init()语句或将它们全部保存在一个文件中将确保在文件移动或名称​​更改时程序的行为不会改变。

Next, we will examine how init() is used to import with side effects.

接下来,我们将检查init()如何用于导入并产生副作用。

使用init()副作用 (Using init() for Side Effects)

In Go, it is sometimes desirable to import a package not for its content, but for the side effects that occur upon importing the package. This often means that there is an init() statement in the imported code that executes before any of the other code, allowing for the developer to manipulate the state in which their program is starting. This technique is called importing for a side effect.

在Go中,有时希望导入软件包不是出于其内容,而是出于导入软件包时发生的副作用。 这通常意味着在导入的代码中有一个init()语句在任何其他代码之前执行,从而使开发人员可以操纵其程序启动的状态。 这种技术被称为导入副作用

A common use case for importing for side effects is to register functionality in your code, which lets a package know what part of the code your program needs to use. In the image package, for example, the image.Decode function needs to know which format of image it is trying to decode (jpg, png, gif, etc.) before it can execute. You can accomplish this by first importing a specific program that has an init() statement side effect.

导入副作用的一个常见用例是在代码中注册功能,这使程序包知道程序需要使用代码的哪一部分。 例如,在image包中 , image.Decode函数需要知道它尝试执行哪种图像格式( jpgpnggif等)后才能解码。 您可以通过首先导入具有init()语句副作用的特定程序来完成此操作。

Let’s say you are trying to use image.Decode on a .png file with the following code snippet:

假设您尝试在具有以下代码段的.png文件中使用image.Decode

Sample Decoding Snippet
样本解码片段
. . .
func decode(reader io.Reader) image.Rectangle {
    m, _, err := image.Decode(reader)
    if err != nil {
        log.Fatal(err)
    }
    return m.Bounds()
}
. . .

A program with this code will still compile, but any time we try to decode a png image, we will get an error.

带有此代码的程序仍会编译,但是每当我们尝试解码png图像时,都会出现错误。

To fix this, we would need to first register an image format for image.Decode. Luckily, the image/png package contains the following init() statement:

要解决此问题,我们首先需要为image.Decode注册一种图像格式。 幸运的是, image/png包包含以下init()语句:

image/png/reader.go
image / png / reader.go
func init() {
    image.RegisterFormat("png", pngHeader, Decode, DecodeConfig)
}

Therefore, if we import image/png into our decoding snippet, then the image.RegisterFormat() function in image/png will run before any of our code:

因此,如果我们导入image/png到我们的解码片断,然后image.RegisterFormat()函数image/png将之前的任何的我们的代码运行:

Sample Decoding Snippet
样本解码片段
. . .
import _ "image/png"
. . .

func decode(reader io.Reader) image.Rectangle {
    m, _, err := image.Decode(reader)
    if err != nil {
        log.Fatal(err)
    }
    return m.Bounds()
}

This will set the state and register that we require the png version of image.Decode(). This registration will happen as a side effect of importing image/png.

这将设置状态并注册我们需要image.Decode()png版本。 该注册将作为导入image/png副作用而发生。

You may have noticed the blank identifier (_) before "image/png". This is needed because Go does not allow you to import packages that are not used throughout the program. By including the blank identifier, the value of the import itself is discarded, so that only the side effect of the import comes through. This means that, even though we never call the image/png package in our code, we can still import it for the side effect.

您可能已经注意到"image/png"之前的空白标识符 ( _ )。 这是必需的,因为Go不允许您导入程序中未使用的程序包。 通过包括空白标识符,导入本身的值将被丢弃,从而仅导入的副作用得以解决。 这意味着,即使我们从不在代码中调用image/png包,我们仍然可以将其导入以产生副作用。

It is important to know when you need to import a package for its side effect. Without the proper registration, it is likely that your program will compile, but not work properly when it is run. The packages in the standard library will declare the need for this type of import in their documentation. If you write a package that requires importing for side effect, you should also make sure the init() statement you are using is documented so users that import your package will be able to use it properly.

了解何时需要导入软件包的副作用非常重要。 如果没有正确注册,则程序可能会编译,但在运行时无法正常运行。 标准库中的软件包将在其文档中声明需要这种类型的导入。 如果编写的程序包需要导入以产生副作用,则还应确保已记录正在使用的init()语句,以便导入程序包的用户将能够正确使用它。

结论 (Conclusion)

In this tutorial we learned that the init() function loads before the rest of the code in your package is loaded, and that it can perform specific tasks for a package like initializing a desired state. We also learned that the order in which the compiler executes multiple init() statements is dependent on the order in which the compiler loads the source files. If you would like to learn more about init(), check out the official Golang documentation, or read through the discussion in the Go community about the function.

在本教程中,我们了解到init()函数在加载包中的其余代码之前先加载,并且它可以为包执行特定的任务,例如初始化所需的状态。 我们还了解到,编译器执行多个init()语句的顺序取决于编译器加载源文件的顺序。 如果您想了解有关init()更多信息,请查看官方的Golang文档 ,或者通读Go社区中有关该函数的讨论 。

You can read more about functions with our How To Define and Call Functions in Go article, or explore the entire How To Code in Go series.

您可以通过《 如何在Go中定义和调用函数》一文来阅读有关函数的更多信息,或浏览整个《如何在Go中编写代码》系列 。

翻译自: https://www.digitalocean.com/community/tutorials/understanding-init-in-go

golang init


http://www.niftyadmin.cn/n/3649744.html

相关文章

MIDP设计模式之集结贴[JavaME]

1:架构性宣言: MIDP 2.0 中的工厂设计模式如何使用 MIDP 的 Generic Connection Frameworkhttp://www-128.ibm.com/developerworks/cn/java/wi-arch22/ 级别: 初级Mikko Kontio, 产品经理, Softera2006 年 3 月 13 日这个月将学习有关 MIDP 2.0 的更多知识,同 Mikko…

计网笔记--网络层

1--网络层概述 网络层主要问题: ① 网络层向运输层提供怎样的服务? (可靠或不可靠) ② 网络层寻址问题(IP 地址) ③ 路由选择问题 (路径) 重点在于:TCP/IP协议栈 2--网络…

Flutter:如何使用WebView插件

Displaying webpages inside of your Flutter applications is easy with the use of the WebView plugin. In our example application, we’ll look at how to create a custom Widget that can be used throughout our application to launch a WebView from anywhere. 显示…

[J2ME]手机流媒体之实作[附源码][与RTSP/MMS协议无关]

郑昀ultrapower产品名称产品版本Keyword: JavaME Streaming Audio MMAPIStreamingDemo1.0.13[J2ME]现行环境下手机实现网络媒体的流畅实时播放之简单演示(StreamingDemo)说明我的资源:http://www.cnblogs.com/Files/zhengyun_ustc/StreamingDemo-src-1.0.13.rar 这个…

[J2ME]增强型二级菜单(增加了三级菜单以及悬浮菜单)

[J2ME]增强型二级菜单演示(AdvdMenuBar)说明我的资源:http://www.cnblogs.com/Files/zhengyun_ustc/AdvdMenuBar-src-1.0.26.rar 这个1.0.26版本的j2me软件,能够在WTK2.3beta的模拟器上运行。本源代码改自SaltedFish的增强版本的AdvdMenuBar,…

[J2ME QA]Target port denied to untrusted applications问题回应

[When]开发J2ME程序的时候,用户可能在运行Socket程序连接远端Socket服务器时出现不受信任的错误,如下面的代码: SocketConnection sc (SocketConnection)Connector.open("socket://localhost:8080");报错为:Uncaught e…

flutter 主题_在Flutter中使用主题

flutter 主题One great aspects of Flutter is its use of UI packages like the Material and Cupertino design systems. They work to shortcut all of the minute and repetitive design choices like the appBar height or the shadows on buttons. But obviously always …

[J2ME QA]untrusted domain is not configured问题回应

[When]第一次使用Netbean 4.0/5.0开发程序的时候,用户可能在运行程序时,遇到下面这种报错,导致模拟器一闪而过:正在通过存储根 DefaultColorPhone 来运行 域名不正确,请切换到 untrustedjava.lang.SecurityException: …