Module 1 basic knowledge of go language – source code file of database

Time:2022-5-6

Have you ever written small commands (or microprograms) in go?

When you are writing “Hello, world”, a source file is enough. Although this gadget is useless, it can give you a little sense of achievement at most. If you are not satisfied with this, don’t worry and follow suit. I’m sure you can also write great programs.

We learned the relevant knowledge of the command source code file in the last article. In addition to the command source code file, you can also write the library source code file in go language. So what is a library source file?

In my definition, a library source file is a source file that cannot be run directly. It is only used to store program entities that can be used by other code (as long as it complies with the go language specification).

The “other code” here can be in the same source file as the program entity used, or in other source files or even other code packages.

So what is the program entity? In go language, program entity is the general name of variables, constants, functions, structures and interfaces. We always declare (or define) program entities before using them. For example, in the previous example, we first defined the variable name, and then called fmt. in the main function It is used in the printf function. To add a little more, the names of program entities are collectively referred to as identifiers. The identifier can be any alphabetic character, number and underscore “” that can be represented by Unicode encoding, But its initial cannot be a number. As a rule, we can use Chinese as the name of the variable. However, I think this naming method is very bad, and I will explicitly prohibit it in the development team. As a qualified programmer, we should approach to writing programs of international standard.

Back to the point.

Our question today is: how to split the code in the command source file into other library source files?

We use code demonstration to make this problem more specific.

If there is a command source file demo4 in a directory Go, as follows:


package main
 
import (
 "flag"
)
 
var name string
 
func init() {
 flag.StringVar(&name, "name", "everyone", "The greeting object.")
}
 
func main() {
 flag.Parse()
 hello(name)
}

You should be familiar with the code. When I talked about the command source file, I pasted a very similar code. The source file is called demo2 go。

The difference between the two files is that demo2 Go directly by calling FMT The printf function prints greetings, while the current demo4 Go calls a function called hello at the same location.

The function Hello is declared in another source file, which I named demo4_ lib. Go, and put it with demo4 Go to the same directory. As follows:

//You need to add code here. [1]
 
import "fmt"
 
func hello(name string) {
 fmt.Printf("Hello, %s!\n", name)
}

So the question comes: what code should be filled in note 1?

Typical answer

The answer is very simple. Fill in the code package declaration statement package main. Why? As I said before, all source files in the same directory need to be declared to belong to the same code package.

If there is a command source file in this directory, in order to compile the files in the same directory, other source files should also be declared to belong to the main package.

In this way, we can run them. For example, we can run the following commands in the directory where these files are located and get the corresponding results.


$ go run demo4.go demo4_lib.go
Hello, everyone!

Alternatively, build the current code package like this before running.


$ go build puzzlers/article3/q1
$ ./q1   
Hello, everyone!

Here, I put demo4 Go and demo4_ lib. Go is placed in a directory with a relative path of puzzlers / Article3 / Q1.

By default, the import path of the corresponding code package will be consistent with this. We can refer to the program entities declared in the code package through the import path of the code package. However, the situation here is different.

Note that demo4 Go and demo4_ lib. Go declares that they belong to the main package. I mentioned this usage when talking about the organization of the source code of go language earlier, that is, the package name declared in the source file can be different from the name of its directory, as long as the package name declared in these files is consistent.

By the way, I created a project called “golang_puzzlers” for this column. The SRC subdirectory of the project will contain all the codes and related files involved.

In other words, the correct usage is that you need to download the package file of the project to any local directory, and then add the “golang_puzzlers” directory to the environment variable gopath after decompression. Remember? This makes the “golang_puzzlers” directory one of the workspaces.

Problem analysis

This question examines the basic rules of code package declaration. Here is another summary.

The first rule is that the code package declaration statement of the source file in the same directory should be consistent. That is, they all belong to the same code package. This applies to all source files.

If there are command source files in the directory, other kinds of source files should also be declared to belong to the main package. This is also the premise that we can successfully build and run them.

The second rule is that the name of the code package declared in the source file can be different from the name of its directory. When building a code package, the main name of the generated result file is consistent with the name of its parent directory.

For the command source file, the main name of the executable generated by the build will be the same as the name of its parent directory, which has also been verified in my previous answer.

Well, after my repeated emphasis, I believe you have remembered these rules. The following will also be relevant to them.

When writing a real program, it is not enough for us to just split the code into several source files. We often use modular programming to put them into different code packages according to their functions and uses. However, this will involve some code organization rules of go language. Let’s go back and forth and have a look.

Intensive knowledge

1. How to split the code in the command source file into other code packages?

Let’s not focus on the technique of splitting code first. I still follow the previous splitting method here. I put demo4 Go save as demo5 Go and put it into a directory with the relative path of puzzlers / Article3 / Q2.

Then I create a directory with the relative path of puzzlers / Article3 / Q2 / lib, and then demo4_ lib. Go make a copy and rename it demo5_ lib. Go to this directory.

Now, how should we modify the code to make them compile? You can think about it first. I’ll give some answers here. Let’s take a look at demo5, which has been modified_ lib. Go file.


package lib5
 
import "fmt"
 
func Hello(name string) {
 fmt.Printf("Hello, %s!\n", name)
}

As you can see, I modified two places here. The first change is that I changed the code package declaration statement from package main to package lib5. Note that I deliberately make the declared package name different from the name of the directory in which it is located. The second change is that I change the all lowercase function name hello to uppercase hello.

Based on the above changes, let’s look at the following questions.

2. Is the import path of the code package always consistent with the relative path of its directory?

Library source file demo5_ lib. The relative path of the directory where go is located is puzzlers / Article3 / Q2 / lib, but it declares that it belongs to the lib5 package. In this case, is the import path of the package puzzlers / Article3 / Q2 / lib or puzzlers / Article3 / Q2 / lib5?

This problem often puzzles beginners of go language. Even those who have developed programs with go may not know it. Let’s have a look.

First, when we build or install this code package, the path provided to the go command should be the relative path of the directory, like this:


go install puzzlers/article3/q2/lib

The command will complete successfully. After that, the corresponding archive files will be generated under the PKG subdirectory of the current workspace. The specific relative path is:


pkg/darwin_amd64/puzzlers/article3/q2/lib.a

Darwin_ AMD64 is the platform related directory I mentioned when talking about the workspace. You can see that the relative path here corresponds to the directory where the source file is located.

In order to further illustrate the problem, I need to demo5 Go makes two changes. The first change is to add puzzlers / Article3 / Q2 / lib to the code package import statement with import as the preamble, that is, to try to import the code package.

The second change is to change the call to the Hello function to lib Call of Hello function. Lib Called qualifier, it aims to indicate the code package where the program entity on the right is located. However, different from the complete writing of the code package import path, it only includes the last level Lib in the path, which is consistent with the rules in the code package declaration statement.

Now, we can run go run demo5 Try the go command. This error is similar to the following prompt.


./demo5.go:5:2: imported and not used: "puzzlers/article3/q2/lib" as lib5
./demo5.go:16:2: undefined: lib

The first error message means that we imported the puzzlers / Article3 / Q2 / lib package, but did not actually use any program entities in it. This is not allowed in the go language and will lead to failure at compile time.

Note that there is another clue here, which is “as lib5”. This shows that although the code package puzzlers / Article3 / Q2 / lib is imported, the program entities in it should be used with lib5 Is a qualifier. This is the reason for the second error prompt. The go command cannot find lib The code package corresponding to this qualifier.

Why? The root cause is that we declare in the source file that the code package we belong to is different from the name of its directory. Remember that the relative path of the directory where the source file is located relative to the SRC directory is its code package import path, and the given qualifier when actually using its program entity should correspond to the code package name to which it belongs.

There are two ways to make the above build complete successfully. I choose demo5 here_ lib. The code package declaration statement in the go file is changed to package lib. The reason is that in order not to confuse the users of the code package, we should always make the declared package name consistent with the name of its parent directory.

3. What kind of program entity can be referenced by the code outside the current package?

You may wonder why I put demo5_ lib. Which function name in the go file is capitalized with the initial of Hello? In fact, this involves the rules of access to program entities in go language.

Super simple. A program entity whose name is capitalized can only be referenced by code outside the current package, otherwise it can only be referenced by other code in the current package.

By name, go language naturally divides the access rights of program entities into package level private and public. For a package level private program entity, even if you import its code package, you can’t reference it.

4. Are there any other access rights rules for program entities?

The answer is yes. In go 1.5 and later versions, we can create internal code packages so that some program entities can only be referenced by other codes in the current module. This is called the third access right of Go program entity: module level private.

The specific rule is that the public program entity declared in the internal code package can only be referenced by the code in the direct parent package and its child packages of the code package. Of course, you need to import the internal package before referencing. For other code packages, importing the internal package is illegal and cannot be compiled.

There is a simple example in the puzzlers / Article3 / Q4 package of the “golang_puzzlers” project for you to view. You can change the code and experience the function of internal package.

summary

In this article, we discussed in detail the method of splitting the code from the command source file, including splitting it into other library source files and other code packages.

Several important basic coding rules of go language are involved here, namely: code package declaration rules, code package import rules and access rights rules of program entities. You must keep these rules in mind when doing modular programming, otherwise your code may not compile.

Thinking questions

  1. If you need to import two code packages, and the last level of the import path of the two code packages is the same, such as dep / lib / flag and flag, will there be a conflict? If there is conflict, how can we solve this conflict in several ways?

This is the end of this article about the basic knowledge of module I go language – library source code file. For more information about the source code file of go language library, please search the previous articles of developeppaer or continue to browse the relevant articles below. I hope you will support developeppaer in the future!