本文介绍了分割客户端/服务器代码的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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



天真的想法是依靠死代码消除,但是从我的简短研究来看,它不是处理任务的可靠方法...... 去构建根本不会消除可能已经通过反射使用的死代码(没有人关心它不是,并且没有选择调整它)。



更坚实的方法似乎是将代码拆分到不同的包中并适当地导入,这似乎是可靠的,但过分复杂化了代码,迫使您在不同软件包之间物理分割某些实体,并时刻牢记这一点。 ..
$ b

最后,还有一些构建标记,允许在为客户端和服务器构建的同一个包中有多个文件。



使用构建标签的动机是我想保持代码尽可能清洁,而不需要引入任何合成实体。使用案例:
有确定的密码学例程,客户端与pub一起工作lic密钥,服务器使用私有...代码在逻辑上属于同一个实体



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

解决方案

这个死代码消除已经由部分工具完成了。 go工具不包括导入包中的所有内容,只包含需要的东西(更确切地说,它排除了它可能无法访问的东西)。

例如,这个应用程序

  package main; import _fmt; func main(){} 

导致几乎300KB的较小的可执行二进制文件(在Windows amd64上)以下内容:

  package main;导入fmt; func main(){fmt.Println()} 

可排除的东西包括函数,类型甚至未导出的导出变量。这是可能的,因为即使使用反射,也不能调用函数或实例化类型,或者只需将它们的名称作为 string 值引用包变量。所以,也许你不应该担心这一点。



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



因此,如果你设计好你的类型和函数,并且你没有创建巨型注册表,你可以列举函数和类型(明确地生成对它们的引用并因此使它们不可解释)二进制文件只包含从导入的包中实际使用的内容。



我不会建议为这类问题使用构建标记。通过使用它们,您将承担额外的责任来维护包或文件依赖关系,否则这些工作将由go工具完成。



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



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


I'm developing a client/server application in golang, and there are certain logical entities that exist both on client and server(the list is limited)

I would like to ensure certain code for this entities is included ONLY in the server part but NOT in the client(wise versa is nice, but not so important).

The naive thought would be to rely on dead code elimination, but from my brief research it's not a reliable way to handle the task... go build simply won't eliminate dead code from the fact that it may have been used via reflection(nobody cares that it wasn't and there is no option to tune this)

More solid approach seems to be splitting code in different packages and import appropriately, this seems reliable but over-complicates the code forcing you to physically split certain entities between different packages and constantly keep this in mind...

And finally there are build tags allowing to have multiple files under the same package built conditionally for client and server

The motivation with using build tags is that I want to keep code as clean as possible without introducing any synthetic entities

Use case:there are certain cryptography routines, client works with public key, server operates with private... Code logically belongs to the same entity

What option would you choose and why?

解决方案

This "dead code elimination" is already done –partly– by the go tool. The go tool does not include everything from imported packages, only what is needed (or more precisely: it excludes things that it can prove unreachable).

For example this application

package main; import _ "fmt"; func main() {}

results in almost 300KB smaller executable binary (on windows amd64) compared to the following:

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

Excludable things include functions, types and even unexported and exported variables. This is possible because even with reflection you can't call a function or "instantiate" types or refer to package variables just by having their names as a string value. So maybe you shouldn't worry about it that much.

Edit: With Go 1.7 released, it is even better: read blog post: Smaller Go 1.7 binaries

So if you design your types and functions well, and you don't create "giant" registries where you enumerate functions and types (which explicitly generates references to them and thus renders them unexcludable), compiled binaries will only contain what is actually used from imported packages.

I would not suggest to use build tags for this kind of problem. By using them, you'll have an extra responsibility to maintain package / file dependencies yourself which otherwise is done by the go tool.

You should not design and separate code into packages to make your output executables smaller. You should design and separate code into packages based on logic.

I would go with separating stuffs into packages when it is really needed, and import appropriately. Because this is really what you want: some code intended only for the client, some only for the server. You may have to think a little more during your design and coding phase, but at least you will see the result (what actually belongs / gets compiled into the client and into the server).

这篇关于分割客户端/服务器代码的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-07 09:55