包声明 - package
在go源文件的开头必须申明文件所属的package,如下所示:
package name
......
一些实验发现
实验 1
注意,位于同一个文件夹下的所有 .go 文件,它们的 package name 一定要完全一致。比如,由于 ccc.go 和 ddd.go 两个文件都位于 bbb 文件夹下,因此这两个文件的 package name 必需要完全一致(但这个 package name 不要求一定为 bbb,即不一定要和所在文件夹的文件夹名称相同)。
如果不一致,则会提示以下错误:
实验 2
一个正确的引用:
aaa/bbb/ccc.go
package cccPackageName
import "fmt"
func SayHello(name string) string {
return fmt.Sprintf("Hello, %s", name)
}
main.go
package main
import "swtest/aaa/bbb"
func main() {
cccPackageName.SayHello("sss")
}
go.mod
module swtest
go 1.13
https://www.digitalocean.com/community/tutorials/how-to-write-packages-in-go
实验 3
结论:在同一个文件夹下的不同文件中的函数,它们在被 import 时,都是 equivalent 的。
aaa/bbb/ccc.go
package bbb
import "fmt"
func SayHello(name string) string {
return fmt.Sprintf("Hello, %s", name)
}
aaa/bbb/ddd.go
package bbb
import "fmt"
func SayHello2(s string) {
fmt.Println(s)
}
main.go
package main
import (
"awesomeProject/aaa/bbb"
)
func test() {
bbb.SayHello("test1")
bbb.SayHello2("test2")
}
go.mod
module awesomeProject
go 1.13
命名规范
- 建议package命名用小写字母
- 建议package命名必和其路径的最后一段一致(main package除外)
- main package中的main方法是可执行文件的入口,main package名可以和路径名不一致
- 不同路径下package命名可以重复,但其完整路径名必须唯一
package 名和导入路径
package的导入路径是指从$GOPATH/src/开始的路径名。例如 package github.com/zhaohuabing/demo 在文件系统中的路径为:$GOPATH/src/github.com/zhaohuabing/demo
Import
package main
import (
"fmt"
"math/rand"
)
func main() {
fmt.Println("My favorite number is", rand.Intn(10))
}
This program is using the packages with import paths "fmt"
and "math/rand"
.
By convention, the package name is the same as the last element of the import path. For instance, the "math/rand"
package comprises files that begin with the statement package rand
.
代码第一行写明package;上例中,希望被执行的文件必须放在其起始处声明package main,否则在go run运行时会报错:”go run: cannot run non-main package“
Multiple Import Ways
常规方式
常规方式,通过包名lib
调用sayHello
方法.lib.SayHello()
import “github.com/libragen/felix/lib”
包名用""
包裹,文件夹层次用/
表示。
普通导入就是按照加载机制,将要使用的包导入进来,然后使用 packageName.MethodName 的方式调用包内的方法即可。注意如果要包方法在其他包中可以调用,包方法需要首字母大写,例如:fmt.Println()
。
别名导入
- 包名过于复杂或者意思不明确. 如使用 mywebapp/libs/mongodb/db 包时,不确定此 db 是哪种类型,故可以使用别名来明确含义:
import mongo "mywebapp/libs/mongodb/db"
- 包名和其他包冲突:世界之大,变化无穷。现在我们有库 db,但没过几年出现了另一种DB,叫云DB。但包名是一样的,分别用别名区分:
import (
"fmt"
myBaz "foo/bar/baz"
ydbgo "mywebapp/libs/yundb/db"
mongo "mywebapp/libs/mongodb/db"
)
func main() {
fmt.Println(myBaz.Hello(), myBaz.World())
}
如果两个包的包名存在冲突,或者包名太长需要简写时,我们可以使用别名导入来解决。
省略package名导入
这里的.
符号表示:在调用包 lib 的成员时,不需要再声明包名。
比如,Println()
是 fmt 包中的方法,在一般的情况下,我们都通过 fmt.Println()
来调用。而使用 . "fmt"
后,直接可以调 Println()
。
package main
import {
. "github.com/libragen/felix/lib"
. "fmt"
}
func main() {
SayHello()
Println("test")
}
下划线操作
package main
import (
"fmt"
_ "foo/bar/baz"
)
func main() {
fmt.Println(baz.Hello(), baz.World()) // 错误 _ 并没有导入包 只是引入并执行包模块的 init 方法
}
_
是包引用操作,只会执行包下各模块中的 init 方法,并不会真正的导入包,所以不可以调用包内的其他方法。
The access after import
a name is exported if it begins with a capital letter. For example, Pizza
is an exported name, as is Pi
, which is exported from the math
package.
pizza
and pi
do not start with a capital letter, so they are not exported.
When importing a package, you can refer only to its exported names. Any “unexported” names are not accessible from outside the package.
package main
import (
"fmt"
"math"
)
func main() {
fmt.Println(math.pi)
}
To fix the error, rename math.pi
to math.Pi
and try it again.