将软件包导入Go的声明性部分相当无聊和平凡。 您只需要指定import
指令并列出导入的软件包。 现代IDE可以为您完成这项工作-它们本身可以替代本节中的软件包,这非常方便。 另外,它们折叠了此块,以免干扰代码视图。 我建议您扩大此范围并仔细研究-也许您会在这里发现一些不寻常的地方:
package main import ( "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" _ "github.com/vigo5190/goimports-example/c" )
如果是标准导入,请使用同义词和_
我遇到,然后从导入.
我没见过
对于初学者来说,值得记住Go程序是如何启动的。
首先也是最重要的事情-在项目的根目录(否则对于库和包)是main.go
文件,该文件在开发时由
go run main.go
该文件的一个显着特征是其中声明的包必须是main
。
package main import ( "fmt" ) func main() { fmt.Println("Hello habr.com!") }
本质上,程序的入口点是main
包中的func main()
。 但是,这种行为可以被破解 。 为此,发明了func init()
函数。 该函数将在执行func main()
之前执行。 此功能也可以写在您的软件包中。 它总是在导入包时执行(准确地说,它将在第一次在程序中导入包时执行)。 还值得理解的是,在运行此程序包的测试时将执行init()
。
包装实例
包a
仅导出变量,而不初始化它。
github.com/vigo5190/goimports-example/a 包b
导出变量并将其初始化为init()
。
github.com/vigo5190/goimports-example/b package b var Foo string func init() { Foo = "bar" }
程序包c
导出变量,将其初始化为init()
并在stdout中显示该值。
github.com/vigo5190/goimports-example/c package c import "fmt" var Foo string func init() { Foo = "bar" fmt.Printf("%#v\n", Foo) }
导入“简单”
在此示例中,我们导入2个程序包,并将导出的变量的值输出到stdout。
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", b.Foo) }
我们得到
go run main.go "" "bar"
这段代码实际发生了什么。 在import
部分,将import
2个软件包a
和b
。 在程序包a
声明了具有默认值a
变量(对于字符串-空字符串)。 在包b
,变量值在init()
中init()
值"bar"
。 要访问每个包的变量,请使用<_>.<_>
形式的条目。
导入同义词
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/b" bar "github.com/vigo5190/goimports-example/a" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", foo.Foo) fmt.Printf("%#v\n", bar.Foo) }
我们得到
go run main.go "" "bar" ""
从示例中可以看到,为包b
分配了同义词foo
。 在这种情况下,包a
导入了几次-第二次在别名bar
。
在几种情况下,可以通过设置同义词来导入包:
- 导入包的名称不便/丑陋/ ...,我想使用另一个名称;
- 导入的名称与另一个包的名称相交;
- 我想无缝替换软件包-软件包接口必须匹配。
正当使用同义词的示例例如,当导入github.com/sirupsen/logrus
:
package db import( log "github.com/sirupsen/logrus" )
下划线导入
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" _ "github.com/vigo5190/goimports-example/c" ) func main() { fmt.Printf("%#v\n", a.Foo) }
我们得到
go run main.go "bar" ""
如代码所示,我们导入两个包: a
和c
。 同时,程序包c
前面有_
,并且程序包本身不以任何方式使用。 该技术用于从包中执行init()
。
在我们的示例中, "bar"
出现在第一行的输出中,因为此输出在包初始化函数c
。
合理使用示例_例如,当导入github.com/lib/pq
:
package db import( _ "github.com/lib/pq" )
在init()
lib/pq
,代码为:
func init() { sql.Register("postgres", &Driver{}) }
这将注册驱动程序。
导入C点
package main import ( "fmt" "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", Foo) }
我们得到
go run main.go "" "bar"
带有点的导入会将包的所有导出字段添加到当前作用域(更确切地说是文件作用域)。 现在,您可以像处理导入包中的字段一样使用它们。
应该非常小心地使用此选项-下面是一个示例。
例子1 package main import ( . "fmt" ) func main() { Println("Hello, habr.com!") }
我们得到:
Hello, habr.com!
例子2 package main import ( . "fmt" . "math" ) func main() { Printf("%v\n", Sqrt(9)) }
我们得到:
3
带点导入(和错误)
package main import ( "fmt" . "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", Foo) }
我们得到
go run main.go
从输出中可以看到,将具有相交字段的包导入当前范围时,会出现编译错误。
因此,在使用这种导入之前,请再三考虑-您可能会完全意外地得到一个错误。
合计
尽管有严格的语法限制,但您仍可以在Go中做很多非标准的事情。 上面讨论的导入功能表明,只需几个操作员,您就可以非常改变程序的行为。 在利用所有这些机会时,最主要的是不要向自己开枪 。 请记住,编写简单易懂的代码要比复杂且“酷”的代码更好。
聚苯乙烯
可以使用的代码示例在github上 。