This is a creation in Article, where the information may have evolved or changed.
In my spare time, I looked through the recently downloaded ebook "Go in Practice", and saw the code demo in the 1.2.4 Package Management section, feeling that the author's assertion of the Go package import seemed imprecise: "Packages is Imported by their name "(subsequent instructions will explain the imprecise reason). Lenovo to a few days ago encountered a Java package import problem, let me vaguely feel the Java programmer is easy to confuse the package import mechanism of the two languages, so I intend to here will be Golang and Java's packages import mechanism to make a comparison, For programmers who transform Java into Golang:). The focus here is on the comparison with Java and the details of the package import for Golang can be found in one of the articles I wrote earlier, "Understanding Golang Packet Import".
Let's take a look at two function-equivalent codes first.
//TestDate.javaimport java.util.*;import java.text.DateFormat;public class TestDate { public static void main(String []args){ Date d = new Date(); String s = DateFormat.getDateInstance().format(d); System.out.println(s); }}
And
//testdate.gopackage mainimport ( "fmt" "time")func main() { t := time.Now() fmt.Println(t.Format("2006-01-02"))}
Both programs output the following when run:
2016-9-13
We see that both Golang and Java are imported using the Import keyword:
import java.util.Date;Date d = new Date();
Vs.
import "time"t := time.Now()
It seems that Java appears to be easier to use after the package import, and when using classes and methods within packages, there is no need to attach the pack name, that is, Date D, not java.util.Date D. When go imports "time", the package name is still attached when referring to the method in the package, for example. Now (). But in essence, the two languages differ greatly in the mechanism of import package.
1. Mechanism
Although import is used, the string following the Import keyword represents a different meaning.
Java import imports a class instead of a package, and the string after import represents a class that is imported on demand, such as import java.util.*, or a class, such as import Java.util.Date. And the string following the Go Import keyword is the package name? Many beginners will think that this is the go package name, in fact, otherwise, the string behind the go import is actually a package import path, which is the reason Java uses "xxx.yyy.zzz" form and Golang use "xxx/yyy/zzz" form. We can prove this with a simple example. We know that Golang will import the package under the XXX/YYY/ZZZ path under \ $GOROOT/src + \ $GOPATH/src, and when we import "FMT", we are actually importing the package under \ $GOROOT/src/fmt directory. It just happens that the name of the package below is the FMT. What would happen if we renamed \ $GOROOT/src/fmt directory to FMT1?
$go build helloworld.gohelloworld.go:3:8: cannot find package "fmt" in any of: /Users/tony/.bin/go17/src/fmt (from $GOROOT) /Users/tony/Test/GoToolsProjects/src/fmt (from $GOPATH)helloworld.go是一个helloworld go源码。
The error is because there is no FMT directory under \ $GOROOT/src, so the two FMT meanings in the following code are different (this also explains the imprecise reason for the statement about package import in Go Practice):
package mainimport "fmt" ---- 这里的fmt指的是$GOROOT/src下的名为"fmt"的目录名func main() { fmt.Println("Hello, World") --- 这里的fmt是真正的包名"fmt"}
We can see from the above that the package name of go and the path of the package source file are not required to be consistent. This is why the go source using the package must be in the form of packagename.xx, rather than Packagename.subpackagename.XX form. For example, after importing "net/http", we use http.xxx in the source code, not net.http.xxx, because Net/http is just a path, not a nested package name.
It seems that the end-segment directory name of the import path matches the package name, just because this is the official go recommendation: The last directory name of the Go Import path (zzz in xxx/yyy/zzz) is the same as the go package name in the source file under the directory (ZZZ).
The following is an example of a non-standard library package name that is completely inconsistent with the import path end segment name:
//github.com/pkgtest/pkg1/foo.gopackage fooimport "fmt"func Foo() { fmt.Println("Foo in pkg1")}//testfoo.gopackage mainimport ( "github.com/pkgtest/pkg1")func main() { foo.Foo() //输出:Foo in pkg1}
You can see that the Testfoo.go import is "Github.com/pkgtest/pkg1″ this path, but the package name under this path is foo."
The packages in the Java language are actually in. jar, and the. Jar internals are actually also organized with a path. class file, for example: Foo.jar This jar contains a package named: Class Foo, Bar in the Com.tonybai.foo,foo packet, That actually foo.jar the internal directory format would be:
foo.jar - com/ - tonybai/ - foo/ - Foo.class - Bar.class
However, for Java package Users, these are transparent.
2. Duplicate name
The only constraint in Java about package import (which is actually a class import) is that you cannot have two classes with the same full name as the imported one, and if there are two imported classes that have the exact same name, Javac in resolve, the order of the classpath path will prevail, Select the class that you encountered first. However, in go, if the package name is the same in the two paths that are imported, go compiler obviously cannot allow this to exist, giving the error message.
For example, we placed the same name in the Gopath under the Github.com/pkgtest/pkg1 and Github.com/pkgtest/pkg2 foo, the following code will be error:
package mainimport ( "github.com/pkgtest/pkg1" "github.com/pkgtest/pkg2")func main() { foo.Foo()}
The error message is as follows:
$go run testfoo.go# command-line-arguments./testdate.go:8: foo redeclared as imported package name previous declaration at ./testfoo.go:7
The way to solve this problem is to use the package alias:
package mainimport ( a "github.com/pkgtest/pkg1" b "github.com/pkgtest/pkg2")func main() { a.Foo() b.Foo()}
Compiling the above program will result in the following instead of error:
Foo of foo package in pkg1Foo in foo package in pkg2
, Bigwhite. All rights reserved.