Stupid way to learn Golang (2): Go Package Basics

Source: Internet
Author: User
Tags uppercase letter hosting sites learn golang
This is a creation in Article, where the information may have evolved or changed.


Today even the general process of personal development may contain more than 10,000 functions, which are generally written and packaged by others as "packages" or "modules", distributed through the communities concerned, and finally developed by software authors by invoking the functions of these "packages" or "modules". So most of the time, the author uses only a small subset of the functions, but reusing the code in the form of "package" or "module" makes programming easier, which is why most programming languages today have their own package management tools and package distribution channels.



In the process of learning the go language, we used almost every example of the Go language pack, such as the FMT, OS and other commonly used features of the built-in package in the go language has more than 100, we are accustomed to call it standard package (standard library), most of these standard packages are built into the go itself. (The full list can be viewed in Go Walker, or the list of standard packages is viewed using the Go List std command).



In the study of this article, the following knowledge points will be included:


    • Understanding of package structure
    • Basic use of the package
    • Common Standard Package detailed
    • Using a custom package


The basis of the package



In most programming languages there is a "package" concept, and any package design is designed to simplify the work of large-scale software design and maintenance, in fact, the package is a collection of functions and data, by putting a set of related features and data into a unit, easy to use and update the corresponding module. This package system is designed so that each module (package) maintains a certain degree of independence from the program and other units (other packages), which allows each module (package) to be applied to different program sections, including other programs, and can even be reused through community distribution channels to projects around the world, It not only reduces the coupling degree between the project modules, but also improves the overall development efficiency.



In the process of writing code, in order to achieve a similar function between different modules (packages) may use the same name to name a function, if a software development process requires the use of two modules (packages), it will be called when the function is ambiguous. To solve this problem, the go language introduces the concept of namespaces. Let each package define a namespace for access to the internal identifiers. Because each namespace is associated with a particular package, this allows us to invoke types and functions with unique, short, and unambiguous names, avoiding naming conflicts when they are used.



In order to improve the independence and security of the package, the go language package can achieve package encapsulation by controlling the visibility of the name in the package, which can greatly improve the security of the software by restricting the visibility of the package members, hiding the concrete implementation process, while the developer calls do not have to care about the implementation process, directly using the package API, On the other hand, the maintainer of the package is allowed to adjust the internal implementation of the package without affecting the user of the package. By restricting the visibility of variables within a package, you can also force users to access and update internal variables through certain functions, which guarantees the consistency of internal variables and the mutually exclusive constraints of concurrency.



Like most compiled languages, in the go language, when we change a source file, we have to recompile the source file and its corresponding package and all other packages that depend on the package. But even from scratch, the go language compiler compiles faster than most compiled languages. This excellent compilation speed is mainly due to the three features of the package design.


    1. Explicit declaration: All imported packages must be explicitly declared at the beginning of each file, so that the compiler does not need to read and parse the entire source file to determine the package dependencies.
    2. No ring dependency: the ring dependency of the packet is forbidden, because there is no cyclic dependency, the dependency of the package forms a direction-free graph, each package can be compiled independently, and it is likely to be compiled concurrently.
    3. No traversal: The target file of the compiled package not only records the export information of the package itself, but also records the package dependencies. Therefore, when compiling a package, the compiler only needs to read the target file of each directly imported package, and it does not need to traverse all dependent files, many of which are repetitive indirect dependencies.


1.1 Structure of the package



In the previous study, we already know that the Go Language compiler tool for the source directory has very strict requirements, each workspace (workspace) must be bin, pkg, src three directory composition. The bin directory mainly contains executable files; The pkg directory holds compiled library files, mainly *.a files; src directory is the main source file for go.


.
|-- bin
|   |-- goimports
|   `-- gophernotes
|-- pkg
|   `-- linux_amd64
|       |-- github.com
|       |   |-- gopherds
|       |   |   `-- gophernotes
|       |   |       |-- internal
|       |   |       |   `-- repl.a
|       ... ...
`-- src
    |-- github.com
    |   |-- gopherds
    ... ...


1. Working space



Because the go language uses workspaces to manage native code, which is not the same as most programming languages, this explains the relationship between Goroot and Gopath. The first obvious point is that Goroot is a global and unique variable that specifies the directory path (the installation path) that holds the go language itself, whereas Gopath is a workspace variable that can have many (delimited) numbers that specify the directory path for the workspace. For example:


GOPATH=$HOME/workspace/golib:$HOME/projects/go


Usually go get uses the first workspace to save the downloaded third-party library (package), which can be used in any workspace, regardless of which workspace the downloaded package is at development time. Note that you should try not to set Goroot and Gopath to the same path.



The source code of the package does not differ from the normal go language, the file must be in the UTF-8 format, and the writing specification is consistent with the Go Language programming specification.



2. Package source Files



The package's code must all be in the package, and the source file header must be consistently declared using the Packages <name> statement. The go package can consist of multiple files, so the file name does not need to match the package name, and the package name suggests using lowercase characters. The package name is similar to the namespace (namespace), regardless of the directory in which the package resides, the name of the compiled file, and the directory name should not use the reserved name (main, all, STD), and the executable file must contain the packages main and the entry function main.



The go language uses the first letter case to determine the access rights of an object (global variables, global constants, types, struct fields, functions, methods), as well as for packages. The initial case of the member name in the package determines the access rights for that member. The first letter is capitalized, can be accessed outside the package, is public (open), and the first letter is lowercase, only the members within the package can access, that is, internal (internal).



Like most modern programming languages, the Go language also supports the use of UTF-8 characters to name objects, so the concept of "capitalization" is not limited to us ASCII, it is extended to all uppercase and lowercase alphabets (including Latin, Greek, Slavic, Armenian and Egyptian prose, etc.). Chinese characters generally have no concept of capitalization (except for Chinese numerals), so if you use kanji as the name of a function, the function is private by default, and you need to precede the Chinese character with an uppercase letter to make it into a public function.



3. Statement of the package



As mentioned above, each package source file needs to be declared at the beginning of the package, which is actually the declaration of the package. The declaration of a package is primarily used in the package for source file compilation to indicate to the compiler what is the source of the package, and in the case of packages, you can use the package name. Function Name method when importing the package.



For cases with the same package name, such as the package names of the Math/rand package and the Crypto/rand package, there is a workaround for the Rand,go language, which we'll cover when we import the package in the next section.



One exception to the declaration of a package is that when a package is compiled to be an executable, we declare the main package in the same way as the package main, when the import path of the main packet itself is irrelevant, and the name is actually a message to the Go Build command, After the package has been compiled, the connector must be called to generate an executable program. (This article does not discuss the case of the test package)



1.2 Import of packages



As explained earlier, the package members are imported before they are used. The keyword for importing a package is import, because the Go Language pack cannot form a ring dependency, and the Go Language Builder will return an error if it encounters an import package loop dependency. Typically, a dependency ring is not easily generated for packages that are downloaded directly from the distribution channel.


import "relative directory / package master file name"


The relative directory refers to a subdirectory starting with <workspace>/pkg/<os_arch>, taking the standard library as an example:


import "fmt" // corresponds to /usr/local/go/pkg/linux_amd64/fmt.a
import "os / exec" // corresponds to /usr/local/go/pkg/linux_amd64/os/exec.a


In addition to the way one package is imported, you can also use a single statement to import multiple packages:


import (
    "fmt"
    "os/exec"
)


1. Import claims



In the previous section we have a problem that is not resolved, that is, the same name when the package import conflict. Although the namespace of the package solves the same name of the function, it does not avoid the case of the name of the package, so the go language can redirect the package names when importing the package to resolve the case of package naming conflicts. For example, here are a few examples:


import "crypto / rand" // default mode: rand.Function
import R "crypto / rand" // package rename: R.Function
import. "crypto / rand" // Easy mode: Function
import _ "crypto / rand" // Anonymous import: Only let this package perform line initialization functions.


Another way to do this:


import (
     "crypto / rand"
     mrand "math / rand" // package renaming
)


Attention:


    1. The go language does not allow importing packages and is not used, and is considered an error at compile time (excluding "import _") if the imported package is not used.
    2. Package renaming can be used not only to resolve package name conflicts, but also to resolve cases where the package name is too long to avoid conflicts with variable or constant names.


In addition to the more common ways to import packages, there are also child package import methods and custom path guidance. For the child packages under the current directory, you can use a relative path in addition to the default full import path.


.
└── src
    └── test
        ├── main.go
        └── test2
            └── test.go

3 directories, 2 files


As the above directory structure, you can import test2 this package in the Main.go file using the following method:


import "test / test2" // Generally we use this method to import
import "./test2" // Relative directories can also be used, but packages imported this way are only valid for go run main.go.


If you import more packages in one file, you can also group the imported packages in order to manage the imported packages in the source code. Groups are separated by a blank line, for example:


import (
    "fmt"
    "html/template"
    "os"

    "golang.org/x/net/html"
    "golang.org/x/net/ipv4"
)


We know that when the go language is compiled, the code is formatted, so the order in which we import the packages doesn't need to be adjusted, and the compilation is automatically sorted alphabetically. We can adjust only the packet grouping, the same packet within each packet at compile time will be formatted alphabetically.



2. Import path



The current go language specification does not enforce the format of the package's import path string, and the import path is explained by the build tool. But if you're going to share or publish a package you've written, it's best to use the world's only import path.



This is mainly to avoid the import of path conflicts, so there is a conventional path format is: All non-standard library package import path to the organization's Internet domain name prefix, so there is a unique path, on the other hand is conducive to packet retrieval.



For example, two of the imported packages below are prefixed with the Internet domain name:


import (
    "fmt"
    "math/rand"
    "encoding/json"
    "golang.org/x/net/html"
    "github.com/go-sql-driver/mysql"
)


3. Custom Paths



In the previous section we used an import path prefixed by a domain name, and for the compiler, only the more popular code-hosting sites can use this path directly. For some personal sites (such as a private Gitlab warehouse built by the enterprise), it is necessary to tell the compiler that this is a package code link in order to make it easier to use this method of importing.



We have three ways to do this, one is directly in the package link to add the VCS format, the currently supported formats are:


Bazaar      .bzr
Git         .git
Mercurial   .hg
Subversion  .svn


For example:


import "example.org/user/foo.git"


The second option is for links that do not provide version control, and go get does not even know how to download the code, such as the following link:


example.org/repo/foo


This is the time to add a tag to the page:


<meta name="go-import" content="import-prefix vcs repo-root">


You can then use the link import:


import "example.org/pkg/foo"


The third case is a redirect page link:



For example, the Go get access link will be redirected to Example.org/r/p/exproj if the following is the case.


<meta name="go-import" content="example.org git https://example.org/r/p/exproj">


If you don't have a server, you can also use the go language to build a simple local server:


package main
import (
    "fmt"
    "net/http"
)
func handler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprint(w, `<meta name="go-import"
    content="example.com/zuolan/test git https://github.com/zuolan/test">`)
}
func main() {
    http.HandleFunc("/zuolan/test", handler)
    http.ListenAndServe(":80", nil)
}


Save As Server.go, and then compile the execution, you can implement to redirect the Example.com/zuolan/test to Github.com/zuolan/test.



Change the Web page (this is also the method of the official website),



1.3 Use of the package



In order to better understand the details of the package import, a package will be created in this section, which is very simple, first set up a project test in the workspace:


mkdir $GOPATH/src/test


Create a new file in Src/test as follows:


package test
// public function
func Even (i int) bool {
       return i% 2 == 0
}
// private function
func odd (i int) bool {
       return i% 2 == 1
}


Then save as a test.go file, and finally compile and install the package using go build and go install commands. Now that we have a package, let's look at how to import the package you just created and apply it to the new program.



To create a new file, it is called main.go (and of course it can be named a different name):


package main
// The following imports the local package test and the official standard package fmt
import (
     "test"
     "fmt"
)
// Call the Even function in the test package. The syntax for accessing functions in a package is package.Function ().
func main () {
       i: = 5
       fmt.Printf ("Is% d even?% v \ n", i, test.Even (i))
} 


In the above example, if you use the odd function, you will get an error when compiling, because the odd function defined in the test package is a private function and cannot be accessed externally.


Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.