Detailed explanation of 8 knowledge points about package import in go language

Time:2021-5-11

1. Single line import and multi line import

In the go language, a package can contain multiple components.goFiles (these files must be in the same level folder), as long as the.goThe header of the file is usedpackageKeyword declares the same package.

There are two ways to import packages

Single line import


import "fmt"
import "sync" 

Multi line import


import(
  "fmt"
  "sync"
)

As you can see, the package imported in Go must be enclosed in double quotation marks, and make complaints about it here.

2. Use alias

In some scenarios, we may need to rename the imported package, such as

When we import two packages with the same package name, there is a conflict. Here we define an alias for one of the packages

import (
  "crypto/rand"
  Mrand "math / Rand" // replace the name with mrand to avoid conflicts
)

We import a package with a long name. In order to avoid writing such a long string of package names, we can define aliases like this


import hw "helloworldtestmodule"

Prevent the imported package name from colliding with local variables, such as path, which is a commonly used variable name, from colliding with the imported standard package.


import pathpkg "path"

3. Point of use operation

For example, in our program, we frequently use a toolkit, such as FMT. Every time we use its print function to print, we need the package name + method name.

For this kind of package using high frequency, it can be defined when it is imported“My own people“By using a.)Our own way is our way.

Since then, we no longer need to add FMT to print.


import . "fmt"

func main() {
  Println("hello, world")
}

However, there is a hidden danger in this usage, that is, there may be functions in the imported package, which may conflict with our own functions.

4. Initialization of package

Each package is allowed to have oneinitFunction. When the package is imported, theinitFunction to do some initialization tasks.

aboutinitThere are two points to note in the execution of functions

initFunction takes precedence overmainFunction execution

In a package reference chain, package initialization is depth first. For example, if there is such a package reference relationship: main → a → B → C, then the initialization order is

C.init→B.init→A.init→main

5. Anonymous import of package

When we import a package, if the package is not used, an error will be reported during compilation.

But in some cases, we import a package and just want to perform the tasks in the packageinitFunction to run some initialization tasks. What should I do at this time?

You can use anonymous import. The usage is as follows. The underline is a blank identifier and cannot be accessed

//Register a PNG decoder
import _ "image/png"

Since the init function will be executed when importing, the package will still be compiled into the executable file when compiling.

6. Is the imported path or package?

When we use import to importtestmodule/fooWhen you are a beginner, you often ask this questionfooIs it a package or just the directory name of the package?


import "testmodule/foo"

In order to reach this conclusion, we made a special experiment (please see the code example in point 7)

When importing, it is imported according to the directory. After importing a directory, you can use all the packages in this directory.

Out of habit, the package name and directory name are usually set to the same, so it gives you the illusion that you are importing a package.

7. Relative Import and absolute import

As far as I know, before go 1.10, it seems that relative import is not supported, but only after go 1.10.

Absolute import: from$GOPATH/srcor$GOROOTperhaps$GOPATH/pkg/modSearch the package under the directory and import it

Relative Import: search for packages from the current directory and start importing. It’s like this


import (
  "./module1"
  "../module2"
  "../../module3"
  "../module4/module5"
)

Let’s take an example

1、 Using absolute import

There is a directory structure like the following (make sure that the current directory is in gopath)

Where main. Go is like this

package main

import (
  "App / utilset" // this method uses absolute path import
)

func main() {
  utils.PrintHello()
}

In the same level directory of main. Go, there is another folderutilsetIn order to make you understand “the sixth point: import imports the path instead of the package”, I define ahello.goThis go file defines the package to which it belongsutils

package utils

import "fmt"

func PrintHello(){
  FMT. Println ("Hello, I'm in the utils package in the utilset directory")
}

The results are as follows

2、 Using relative Import

Or the above code, change the absolute import to relative import

Set gopath path back (please compare gopath with absolute path above)

Then run it again

To sum up, there are two points to note when using relative import

Don’t put the project in front of you$GOPATH/srcIf I change the current project directory to gopath, an error will be reported

Go modules does not support relative import. After you open go111module, you cannot use relative import.

Finally, it has to be said that the project readability will be greatly reduced by using the relative import method, and the developer will not be used to clarify the whole reference relationship.

Therefore, absolute reference is generally recommended. If you use absolute references, you have to talk about priorities

8. Priority of package import path

In the previous section, we introduced three different package dependency management schemes. For different management modes, the paths for storing packages may be different. Some packages can be placed under gopath, some packages can be placed under vendor, and some packages are built-in packages under goroot.

Then the problem arises. If there is a package with the same package name but different versions under these three different paths, which one should we choose to import?

This requires us to understand the priority of package search path in golang?

At this time, we need to distinguish which mode is used for package management.

If govendor is used

When we import a package, it will:

  • First, search the vendor directory in the root directory of the project
  • Finally, find it in the $root / SRC directory
  • Then look up it from the $gopath / SRC directory
  • If you can’t find them, you will report an error.

In order to verify this process, I create a vendor directory in the creation process, and then open the vendor mode. I randomly import a package PKG in main.go. Because this package is randomly specified by me, I can’t find it. If I can’t find it, I will report an error. Golang will print out the search process in the error information, and from this information, You can see golang’s packet lookup priority.

If you use go modules

If the package you import has a domain name, it will be in the$GOPATH/pkg/modIf you can’t find it, go to the website to find it. If you can’t find it or it’s not a package, an error will be reported.

If the package you import does not have a domain name (such as “FMT”), it will only arrive at$GOROOTFind it in the library.

Another important point is that when you have a vendor directory under your project, no matter whether your package has a domain name or not, you will only look for it in the vendor directory.

usuallyvendorDirectory is throughgo mod vendorCommand, this command will package all project dependencies into your project directory in the verdor folder.

Extended readingHow to use go module to import local package

Here is the article about the detailed explanation of 8 knowledge points about package import in go language. For more information about the import content of go language package, please search the previous articles of developer or continue to browse the following related articles. I hope you can support developer more in the future!