有没有任何习惯用于生成/预处理解决方案的库?

huangapple go评论91阅读模式
英文:

Any idiomatic generate/preprocessing solution library?

问题

我真的很喜欢Go语言,但是在处理错误和与其他语言使用同步数据类型时,它让我感到很困惑。对于C/C++,我可以很容易地使用宏来处理这些问题,而Go开发者则说Go的惯用解决方案是代码生成,但我没有找到现成的解决方案。

所以基本上,我需要的是像这样的东西:

  1. 读取源代码,对于每个类型的使用,检查它是否在特殊的配置文件中列出。如果是,则用配置文件中的类型替换它。
  2. 读取源代码,对于每个函数,检查它是否在配置文件中列出。如果是,则用配置文件中的代码片段和模板替换它,并在需要时添加必要的导入。
  3. 可能需要根据返回值添加一些多态性,以防止类型转换。
  4. 也许需要添加(err error)逻辑。不确定这是否是一个好主意。

就像这样:

code.go

func getConn(id platform.UUID) (res1 string, res2 platform.res) {
  res1 = driver_native_res(id)
  res2 = driver_native_res(id)
  return
}

code-gen.go

import (
  "linux"
)
func getConn(id uint64) (res1 string, res2 int32, err error) {
  res1, err = linux.GetResAsString(id)
  if err != nil {
    return
  }
  res2, err = linux.GetRes(id)
  if err != nil {
    return
  }
  return
}

我知道go AST,但是似乎用它来实现这样的功能不太快。我希望有一些更简单的解决方案。

英文:

I really like Go but makes me crazy about if-err hell and when I have sync datatypes in Go code with other languages. For C/C++ I can easily deal such stuff with macros, while Go developers say the idiomatic solution for Go is code generation, but I didn't find any out-of-the-box solution.

So basically, what I need is something like

  1. Read the source, for every type usage check if it is listed in special config file. If it is, then change it with the one from config.
  2. Read the source, for every function check if it is listed in config file. If it is then, change it with the code snippet from config by template and add neccessary import if it's missing.
  3. Probably, add some polymorphism based on return values to prevent type casts.
  4. Maybe, add (err error) logic. Not sure it's a good idea.

Like this

code.go

func getConn(id platform.UUID) (res1 string, res2 platform.res) {
  res1 = driver_native_res(id)
  res2 = driver_native_res(id)
  return
}

code-gen.go

import (
  "linux"
)
func getConn(id uint64) (res1 string, res2 int32, err error) {
  res1, err = linux.GetResAsString(id)
  if err != nil {
    return
  }
  res2, err = linux.GetRes(id)
  if err != nil {
    return
  }
  return
}

I know about go AST, but seems like it's not very fast to implement such features with it. I hope there is some easier solution.

答案1

得分: 0

正如你所发现的,Go语言中没有宏,并且也不太可能会有。不过可能会有泛型在某个时候会有所帮助。与此同时,有几种选项可以用于代码生成。你可以使用go generate来实现:

在你的Go文件中添加一个特殊的注释,用于需要额外生成的代码。例如,下面的代码会调用一个名为stringer的工具进行生成,当然也可以是yacc或者一些自定义的工具。

// add a magic comment to your go file 
// which needs some extra generated code
// this calls a tool called stringer to generate, 
// but it could be yacc or some homemade tool. 
//go:generate stringer -type=Pill

// call go generate to generate the methods:
go generate

详细信息可以参考:https://blog.golang.org/generate

但是这种方法需要你有一个能够生成所需代码的工具,比如stringer。

或者你可以使用text/template,构建自己的模板,并运行一个简单的工具将值替换到模板中(可以从配置文件中获取,或者通过命令行参数传递)。

mytool generate -type=thing -field=type...
... mytool loads a tmplate file, 
runs it through text/template and outputs it. 

这种方法非常直接,你可以很容易地构建一个自定义系统,不过你可能会希望只生成一次代码,然后重复使用。以下是一些使用这种方法的示例:

http://clipperhouse.github.io/gen/

https://github.com/fragmenta/fragmenta

最后,你可以使用像gRPC这样的工具,在多种语言中生成结构体,以便简化跨语言通信,这似乎正是你所需要的用例:

https://grpc.io/docs/quickstart/go.html

我建议你首先看一下类似gRPC的工具。

英文:

As you have discovered, there are no macros and are unlikely to be. There may be generics at some point which could be helpful. In the meantime, there are a few options for code generation. You can use go generate for this:

// add a magic comment to your go file 
// which needs some extra generated code
// this calls a tool called stringer to generate, 
// but it could be yacc or some homemade tool. 
//go:generate stringer -type=Pill

// call go generate to generate the methods:
go generate

https://blog.golang.org/generate

But it really requires you to have a tool to generate the code you want like stringer.

Or you could just use text/template, build your own template, and run a simple tool that substitutes values into this template (from a config file, or perhaps arguments on the command line).

mytool generate -type=thing -field=type...
... mytool loads a tmplate file, 
runs it through text/template and outputs it. 

This is pretty straightforward and you could easily build a custom system with it, though you'll probably want to generate once, then use the code. Here are some examples of this approach:

http://clipperhouse.github.io/gen/

https://github.com/fragmenta/fragmenta

Finally, you can use tools like grpc which generate structs in multiple languages in order to ease cross-language communication, which sounds like exactly the use case you are looking for:

https://grpc.io/docs/quickstart/go.html

I'd look at something like grpc first.

huangapple
  • 本文由 发表于 2017年8月11日 03:47:27
  • 转载请务必保留本文链接:https://go.coder-hub.com/45622348.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定