拆分客户端/服务器代码

时间:2016-08-10 13:36:01

标签: go server client

我正在golang中开发一个客户端/服务器应用程序,并且客户端和服务器上都存在某些逻辑实体(列表有限)

我想确保这些实体的某些代码仅包含在服务器部分中,但不包含在客户端中(反之亦然,但不是那么重要)。

天真的想法是依赖于死代码消除,但是根据我的简短研究,它不是处理任务的可靠方法...... go build根本不会消除死代码已被反射使用(没有人关心它不是,没有选择来调整它)

更加可靠的方法似乎是在不同的包中拆分代码并进行适当的导入,这似乎是可靠的,但过于复杂的代码迫使您在不同的包之间物理地拆分某些实体并且始终牢记这一点......

最后,有一些构建标签允许在客户端和服务器有条件地构建的同一个包下有多个文件

使用构建标记的动机是我希望在不引入任何合成实体的情况下保持代码尽可能干净

用例: 有一些加密例程,客户端使用公钥,服务器使用私有...代码逻辑上属于同一个实体

您会选择什么选项?为什么?

1 个答案:

答案 0 :(得分:2)

这个“死代码消除”已经完成 - 部分由go工具完成。 go工具不包括导入包中的所有内容,只包含所需内容(或更准确地说:它排除了无法访问的内容)。

例如此应用程序

package main; import _ "fmt"; func main() {}
与以下相比,

导致几乎300KB的可执行二进制文件(在windows amd64上):

package main; import "fmt"; func main() {fmt.Println()}

可排除的东西包括函数,类型甚至未导出和导出的变量。这是可能的,因为即使使用反射,也不能通过将其名称作为string值来调用函数或“实例化”类型或引用包变量。所以也许你不应该为此担心。

编辑:随着Go 1.7发布,它甚至更好:阅读博文:Smaller Go 1.7 binaries

因此,如果你很好地设计你的类型和函数,并且你没有创建“巨型”注册表,你枚举函数和类型(显式生成对它们的引用,从而使它们不可识别),编译的二进制文件将只包含什么是实际上是从导入的包中使用的。

我不建议使用构建标记来解决这类问题。通过使用它们,您将有额外的责任自己维护包/文件依赖性,否则将由go工具完成。

您不应该将代码设计和分离到包中,以使输出可执行文件更小。您应该根据逻辑设计代码并将其分离到包中。

我会在真正需要的时候把东西分成包,并适当导入。因为这真的是你想要的:一些代码仅用于客户端,一些仅用于服务器。在设计和编码阶段你可能需要多考虑一下,但至少你会看到结果(实际属于/被编译到客户端和服务器中)。