英文:
C-style macros in Go
问题
我已经用Go玩了一个星期,我想念C语言中的预处理宏。
除了通过一个构建脚本将Go文件通过clang -E
进行处理之外,我还能用什么来实现这个功能?
英文:
I've been playing with go for a week and something I miss from C is preprocessor macros.
What could I use to get this feature, besides hacking a build script that pipes go files through clang -E
?
答案1
得分: 8
如评论中所提到的,构建标志可能是解决您所需问题的最佳方法。例如,如果您希望在开发中仅可用某些功能,请使用dev
标志:
文件constants_dev.go:
// +build dev
const DEVELOPMENT = true
文件constants_pro.go:
// +build !dev
const DEVELOPMENT = false
然后在您的代码中,只需简单地使用if DEVELOPMENT { blah... }
。我发现这比任何预处理器更易读。如果您有很多构建标志,这可能会变得非常混乱,但在那时,您应该考虑使用命令行参数。
在您的评论中,您提到了代码重复的问题。如果您的代码确实如此重复,您应该考虑将其放入一个函数中,或者可能重构代码以重用重复的部分。就个人而言,我发现除了简单的布尔检查之外的任何内容都会导致难以维护的代码,特别是使用C风格宏。
泛型也是如此。在我使用过的一个Java库中,类的签名大致如下:
class Thing<A, B, C, D, E>
该库的文档不是很好,所以我不得不阅读大量代码(包括实现和使用该库的代码)才能理解发生了什么。
在Go中,语言强制使用一种通常会导致更好、自我说明的代码的风格。我认为Go开发人员省略了预处理器和泛型等内容,以避免编写难以维护但聪明的代码的诱惑。
我建议您在回顾以前使用的旧习惯之前尝试Go的方式。我认为您会发现大多数宏和#define用于的内容在很大程度上是无关紧要的。
英文:
As mentioned in the comments, build flags are probably the best way to solve whatever you need. For example, if you wanted to have some features only available in development, use a dev
flag:
File constants_dev.go:
// +build dev
const DEVELOPMENT = true
File constants_pro.go
// +build !dev
const DEVELOPMENT = false
Then in your code, just do a simple if DEVELOPMENT { blah... }
. I find this much more readable than any preprocessor. This can get quite messy if you have a lot of build flags, but at that point you should probably be using command-line arguments instead.
In your comment, you mentioned duplication of code. If your code is really that repetitive, you should probably be putting it in a function anyway, or possibly restructure code to reuse the bits that are repetitive. Personally, I find that anything beyond simple boolean checks ends in hard to maintain code, especially with C-style macros.
It's the same thing with generics. In one Java library I've used, the class signature was something like this:
class Thing<A, B, C, D, E>
The library wasn't very well documented, so I had to read a significant amount of the code (both implementation and code that uses the library) to understand what was going on.
In Go, the language forces a style that generally leads to better, self-documenting code. I think the Go developers omitted things like a preprocessor and generics to avoid temptation to write hard to maintain, but clever, code.
I would advise you to try out the Go way before looking back on old idioms that you used before. I think you'll find that most of what macros and #defines were used for are largely irrelevant.
答案2
得分: 5
我认为cpp、m4或其他工具可能能够满足您对于预处理Go代码的需求。是否是一个好主意取决于您自己,但请注意,任何预处理都会对采用任何已发布的Go代码构成重大障碍。(例如,构建依赖于makefile也是同样的情况。)
英文:
I think cpp, m4 or whatever may fulfill your desire to have Go preprocessed. If it's a good idea or not is a decision of yours, but be warned that any preprocessing is a substantial obstacle for adoption of any published Go code. (And for example, the build being dependent on makefiles is the same story.)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论