【发布时间】:2021-01-04 18:05:14
【问题描述】:
golang包中未使用的const/function/struct方法是否包含在可执行二进制文件中?
例如:
- 如果我有一个包
Const,其中包含一堆常量(包含SQL 查询),但在main中使用的常量很少,编译时会全部包含在可执行二进制文件中吗?
package Const
const (
InsertA = `insert into ...`
InsertB = `insert into ...`
UpdateA1 = `update ...` // certain column
UpdateA2 = `update ...` // other columns, different where, etc..
...
)
// in main, only some of them used/prepared
- 如果我有一个包
Func,其中包含一堆返回文字(SQL 字符串)的函数,但在main中只使用了几个函数,编译时是否会全部包含在可执行二进制文件中?
package Func
func InsertA() string { return `insert into ...` }
func InsertB() string { return `insert into ...` }
func UpdateA() string { return `Update ...` }
...
- 如果我有一个包
mix,其中包含返回/使用所有常量的函数(如数字1),但只有main中使用的一些函数在编译时会全部包含在可执行二进制文件中吗?
package mix
const (
insertA = `insert into ...`
insertB = `insert into ...`
updateA = `update ...`
...
)
func InsertA() string { return insertA }
func InsertB() string { return insertB }
func UpdateA() string { return updateA }
// in main, only some of the const are prepared
- 如果我有一个包
Struct,其中包含许多带有一堆方法的结构(每个表的分类SQL),但只有main中调用的一些结构,将所有常量,结构定义,包括的方法编译时在可执行二进制文件中?
package Struct
const (
insertA = `insert into ...`
insertB = `insert into ...`
updateA = `update ...`
...
)
// in main only some of them prepared
type A struct {db *DB}
func (a *A) Prepare() error {}
func (a *A) InsertA(...) error {}
func (a *A) UpdateA(...) error {}
type B struct {db *DB}
func (b *B) Prepare() error {}
func (b *B) InsertB(...) error {}
// in main only some of them used (eg. only struct `A` used)
上下文/案例用于重构旧代码库,因此它可以更好地调试/理解新程序员的代码(通过合并每个表一个结构或一个包来轻松了解哪些函数/方法修改该表)表)而不牺牲二进制大小,因为目前所有命令查询都分散在多个二进制文件/包中(必须手动 ctrl+F INSERT INTO tablename 或 UPDATE tablename 或 DELETE FROM tablename 以查看哪些函数/方法在其上写入/修改记录桌子)。
所以我可以决定是为每个表(250+)一个包更好,还是一个包包含多个包含每个表的空结构的文件。
旧代码库是这样的:
package hugeX
func foo() map[constQ]string {
return map[constQ]string{
insertB: `insert into...`,
updateA: `update ...`,
...
}
}
package hugeY
func foo() map[constQ]string {
return map[constQ]string{
insertA: `insert into...`,
updateB: `update ...`,
...
}
}
package foo
const (
insertB = `insert into..`
updateA = `update ...`
...
)
package bar // importing hugeX
const (
insertA = `insert into ...`
updateA = `update ...` // by something, sometimes duplicates
...
)
package baz
const (
...
)
... and so on..
【问题讨论】:
-
这是一个内部编译器实现细节,可能因编译器版本和目标而异。不过,关于此代码,您可能仍需要考虑重构。包应该以功能为导向,而不是它们使用的语言结构;永远不应该有包
const,或func,或struct。包名也应该全部小写。这段代码将很快变得无法维护,任何其他 Go 开发人员都很难按原样理解它。 -
在 golang-nuts 邮件列表上有一个关于这个的问题。答案是:链接器只包含被 main 引用的函数,并且包含所有被引用类型的所有方法。
-
我赞同 Adrian 重构代码的建议。
-
通常常量不作为单独的实体包含在二进制文件中。它们是不可寻址的常量值,而不是变量。但是,它们的存储方式是一个实施决定。
-
确实常量根本没有编译到二进制文件中。无论常量名称出现在何处,编译器都会将其替换为常量的值。这就是常量的意义所在。
标签: function go methods struct constants