示例 4.1 hello_world.go
package main
import "fmt"
func main() { fmt.Println("hello, world") }
4.2.1 包的概念、导入与可见性
Go 的标准库包含了大量的包(如:fmt 和 os),但是你也可以创建自己的包(第 8 章)。
如果想要构建一个程序,则包和包内的文件都必须以正确的顺序进行编译。包的依赖关系决定了其构建顺序。
属于同一个包的源文件必须全部被一起编译,一个包即是编译时的一个单元,因此根据惯例,每个目录都只包含一个包。
如果对一个包进行更改或重新编译,所有引用了这个包的客户端程序都必须全部重新编译。
Go 中的包模型采用了显式依赖关系的机制来达到快速编译的目的,编译器会从后缀名为 .o
的对象文件(需要且只需要这个文件)中提取传递依赖类型的信息。
如果 A.go
依赖 B.go
,而 B.go
又依赖 C.go
:
- 编译
C.go
,B.go
, 然后是A.go
. - 为了编译
A.go
, 编译器读取的是B.o
而不是C.o
.
这种机制对于编译大型的项目时可以显著地提升编译速度。
如果包名不是以 .
或 /
开头,如 "fmt"
或者 "container/list"
,则 Go 会在全局文件进行查找;如果包名以 ./
开头,则 Go 会在相对目录中查找;如果包名以 /
开头(在 Windows 下也可以这样使用),则会在系统的绝对路径中查找。
导入包即等同于包含了这个包的所有的代码对象。
除了符号 _
,包中所有代码对象的标识符必须是唯一的,以避免名称冲突。但是相同的标识符可以在不同的包中使用,因为可以使用包名来区分它们。
包通过下面这个被编译器强制执行的规则来决定是否将自身的代码对象暴露给外部文件:
可见性规则
当标识符(包括常量、变量、类型、函数名、结构字段等等)以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用(客户端程序需要先导入这个包),这被称为导出(像面向对象语言中的 public);标识符如果以小写字母开头,则对包外是不可见的,但是他们在整个包的内部是可见并且可用的(像面向对象语言中的 private )。
(大写字母可以使用任何 Unicode 编码的字符,比如希腊文,不仅仅是 ASCII 码中的大写字母)。
因此,在导入一个外部包后,能够且只能够访问该包中导出的对象。
假设在包 pack1 中我们有一个变量或函数叫做 Thing(以 T 开头,所以它能够被导出),那么在当前包中导入 pack1 包,Thing 就可以像面向对象语言那样使用点标记来调用:pack1.Thing
(pack1 在这里是不可以省略的)。
因此包也可以作为命名空间使用,帮助避免命名冲突(名称冲突):两个包中的同名变量的区别在于他们的包名,例如 pack1.Thing
和 pack2.Thing
。
你可以通过使用包的别名来解决包名之间的名称冲突,或者说根据你的个人喜好对包名进行重新设置,如:import fm "fmt"
。下面的代码展示了如何使用包的别名:
示例 4.2 alias.go
package main
import fm "fmt" // alias3 func main() { fm.Println("hello, world") }
注意事项
如果你导入了一个包却没有使用它,则会在构建程序时引发错误,如 imported and not used: os
,这正是遵循了 Go 的格言:“没有不必要的代码!“。
函数 Printf
可以在 fmt 包外部使用,这是因为它以大写字母 P 开头,该函数主要用于打印输出到控制台。通常使用的格式化字符串作为第一个参数:
func Printf(format string, list of variables to be printed)
在示例 4.5 中,格式化字符串为:"The operating system is: %s\n"
。
这个格式化字符串可以含有一个或多个的格式化标识符,例如:%..
,其中 ..
可以被不同类型所对应的标识符替换,如 %s
代表字符串标识符、%v
代表使用类型的默认输出格式的标识符。这些标识符所对应的值从格式化字符串后的第一个逗号开始按照相同顺序添加,如果参数超过 1 个则同样需要使用逗号分隔。使用这些占位符可以很好地控制格式化输出的文本。
函数 fmt.Sprintf
与 Printf
的作用是完全相同的,不过前者将格式化后的字符串以返回值的形式返回给调用者,因此你可以在程序中使用包含变量的字符串,具体例子可以参见示例 15.4 simple_tcp_server.go。
函数 fmt.Print
和 fmt.Println
会自动使用格式化标识符 %v
对字符串进行格式化,两者都会在每个参数之间自动增加空格,而后者还会在字符串的最后加上一个换行符。例如:
fmt.Print("Hello:", 23)
将输出:Hello: 23
。
摘自:https://github.com/Unknwon/the-way-to-go_ZH_CN/blob/master/eBook/04.2.md
本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/bonelee/p/6860860.html,如需转载请自行联系原作者