Go36-3-Code Pack

Splitting code into multiple files

If the code is too complex, you can write it in multiple source files. Or in other code packages (later on)

Code example

Here is the body of the program, but it calls the square() function, which does not declare:

// Go36/article03/example01/demo.go
package main

import (
    "flag"
    "fmt"
)

var x int

func init() {
    flag.IntVar(&x, "x", 0, "Square of computation")
}

func main() {
    flag.Parse()
    res := square(x)
    fmt.Println(x, "Squared:", res)
}

The square() function used above is declared in another file:

// Go36/article03/example01/calc.go
package main

func square(x int) int {
    return x * x
}

Only one function is declared here, and more functions about computation can be written here, so that these functions can be easily called in the same package.
Both of the above files are in the same directory and need to be declared to belong to the same package.

Execution code

Because the examples are declared as main packages, and there is also a main function in the packages. So there is a command source file so that it can run directly:

PS H:\Go\src\Go36\article03\example01> go run demo.go calc.go -x 3
3 Squared: 9
PS H:\Go\src\Go36\article03\example01>

It's important to write all the files in the command.
You can also build code packages first and execute them:

PS H:\Go\src> go build Go36/article03/example01
PS H:\Go\src> .\example01.exe -x 4
4 Squared: 16
PS H:\Go\src>

Splitting code into multiple packages

Firstly, modify the path of calc.go and make some modifications:

// Go36/article03/example02/lib/calc.go
package lib2

func Square(x int) int {
    return x * x
}

A subdirectory is created here, and the files are placed in this subdirectory, so that it is not in the same directory as the command source files.
Some modifications have also been made to the parallel code:

  1. The package name becomes lib2, where the intent and directory are not the same name
  2. The initials of function names are capitalized

Package and directory names are different

Now use the bag above. The path to import the package should be the path name of the directory:

import (
    "Go36/article03/example02/lib"
)

If you want to build or install this code package, the command should be the following or the directory name:

go install Go36/article03/example02/lib

And after the command succeeds, the file generated by the pkg subdirectory is also the directory name:

pkg\windows_amd64\Go36\article03\example02\lib.a

However, the package name is required for the final invocation. The code of the command source file is as follows:

// Go36/article03/example02/demo.go
package main

import (
    "flag"
    "fmt"
    "Go36/article03/example02/lib"
)

var x int

func init() {
    flag.IntVar(&x, "x", 0, "Square of computation")
}

func main() {
    flag.Parse()
    res := lib2.Square(x)
    fmt.Println(x, "Squared:", res)
}

The lib2. used when calling the program above is called a qualifier.
Conclusion: The import path uses the path of the directory where the file is located. The qualifier used when calling a program is the same as the package name it declares.
In order not to use code packages is confusing, the name of the declared package should be consistent with the directory name of its parent directory.

Access right

The reason for changing the initials of function names to uppercase here is that program entities whose initials are uppercase can only be referenced by code outside the current package, otherwise it can only be referenced by other code within the current package.
This involves the rules of access rights to program entities in Go language. By capitalizing the initials of the names, access rights are divided into package-level private and public. For package-level private, it is accessible only within the package. Since we need to call the lib package function in the main package, we can only access the public part, so we need to capitalize the function's initials.

Modular Private
The access permissions above are divided at the package level. In Go 1.5 and subsequent versions, you can create internal code packages so that some program entities can only be referenced by other code in the current module. This is the third access privilege: module-level private.
The rule is that public program entities declared in an internal code package can only be referenced by the direct parent package and the code in its subpackage. Of course, you need to import the internal package before you reference it. For other code packages, importing the internal package is illegal and cannot be compiled.
The name here must be internal, as shown below:

// The parent directory Go36/article03/example03/demo.go
package main

import (
    "flag"
    "Go36/article03/example03/lib"
    //"Go36/article03/example03/lib/internal"//This line cannot be compiled.
)

var x int

func init() {
    flag.IntVar(&x, "x", 0, "Square of computation")
}

func main() {
    flag.Parse()
    lib.Cale(x)
    //res := internal.Square(x)
    //lib.Cale(res)
}

// Subdirectory Go36/article03/example03/lib/demo_lib.go
package lib

import (
    "fmt"
    "Go36/article03/example03/lib/internal"
)

func Cale(x int) {
    res := internal.Square(x)
    fmt.Println(x, "Squared:", res)
}

// Sun Tzu Directory Go36/article03/example03/lib/internal/internal.go
package internal

func Square(x int) int {
    return x * x
}

Module-level private internal packages can only be referenced by code in direct parent packages and their subpackages. It is illegal to call the internal package of the Sun directory in the parent level.

PS H:\Go\src\Go36\article03\example03> go run demo.go -x 7
demo.go:6:2: use of internal package not allowed
PS H:\Go\src\Go36\article03\example03>

Keywords: Go

Added by step on Wed, 15 May 2019 19:58:52 +0300