我的问题如下:
你认为这可能吗?
我做了一些研究,似乎不太可能,但我可能忽视了一些事情。
谢谢:)
第一个二进制文件包含类似
的内容func main() {
// Here I need to compile an external go file (or package) which contains
// The definition of runFoo()
// Once the file/package is compiled and linked I need to call the compiled code
runFoo()
// Continue the execution process normally here
}
答案 0 :(得分:21)
创建共享库的能力将在2015年8月的Go 1.5中进行。
来自安德鲁·格兰德的“The State of Go”演讲:
共享库
Go 1.5可以生成Go可以使用的Go共享库 程序
将标准库构建为共享库:
$ go install -buildmode=shared std
构建一个链接共享的“Hello,world”程序 库:
$ go build -linkshared hello.go $ ls -l hello -rwxr-xr-x 1 adg adg 13926 May 26 02:13 hello
Go 1.5也可以将Go程序构建为C档案文件(对于静态文件) 可以是链接)或共享库(用于动态链接) 被C程序消耗。
¹请注意,gccgo
已经有一段时间对此有一定的支持,Go 1.5将是常规go构建工具第一次支持。
答案 1 :(得分:10)
更新:现在可以在主线Go中执行此操作,请参阅Go Execution Modes
仅对于amd64架构,编译器有一个新选项, -dynlink,它通过支持对外部共享库中定义的Go符号的引用来协助动态链接。
旧答案(对其他选项的有用讨论):
目前无法在主线Go中创建动态链接库*。有一些关于此的讨论,所以你可能会看到将来的支持。但是,有一个名为goandriod的第三方项目需要您需要的相同功能,因此他们维护的补丁应该允许您修补官方Go代码库以支持您请求的动态链接支持。
如果您想使用标准的Go运行时,我建议您使用以下其中一项。 从您的其他程序调用您的Go程序,并使用以下方式进行通信:
每个连续选项都需要花费更多精力进行设置,更具针对性,但可能比前一个更强大。
*注意:这是Windows世界中的DLL,以及UNIX / Linux世界中的.so文件。
答案 2 :(得分:3)
我认为go plugins也可能与此问题有关,因为go版本1.8支持它们。它允许您在运行时动态链接go二进制文件,以实现所需的接口。
例如,您的代码对日志记录后端具有依赖性,但是您想支持其中的几个并在运行时解决它,elasticsearch
和splunk
可能适合这里。
您可能需要有2个文件:es.go
和splunk.go
,它们都应包含实现方法LoggingBackend
的类型Write(log string)
的结构。
要创建插件,您需要在编译过程中使用构建模式plugin
:
go build -buildmode = plugin -o es.so es.go
go build -buildmode = plugin -o splunk.so splunk.go
之后,您可以通过命令行参数传递所需的插件并加载它:
package main
import "plugin"
import "flag"
type LoggingBackend interface {
Write(log string)
}
var (
backend = flag.String("backend", "elasticsearch", "Default logging backend is elasticsearch")
)
func main() {
flag.Parse()
var mode string
switch backend {
case "elasticsearch":
mode = "./es.so"
case "splunk":
mode = "./splunk.so"
default:
fmt.Println("Didn't recognise your backend")
os.Exit(1)
plug, _ := plugin.Open(mod)
loggingBackend, _ := plug.Lookup("LoggingBackend")
logWriter, _ := loggingBackend.(LoggingBackend)
logWriter.Write("Hello world")
}
答案 3 :(得分:2)
这很有可能,您甚至可以将其编译为本机共享库
go build -buildmode=c-shared goc.go
# file goc
goc: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV),
dynamically linked,
BuildID[sha1]=f841e63ee8e916d7848ac8ee50d9980642b3ad86,
not stripped
nm -D - 仅限定义./goc | grep“T”
0004ebe8 T _cgoexp_f88ec80374ab_PrintInt
000a6178 T _cgo_panic
0004e954 T _cgo_sys_thread_start
000a48c8 T _cgo_topofstack
0004e88c T _cgo_wait_runtime_init_done
000a61a4 T crosscall2
0004ebc8 T crosscall_arm1
0004e7b0 T fatalf
00102648 T _fini
0004e544 T _init
0004e76c T PrintInt
0004ebe4 T __stack_chk_fail_local
0004eb5c T x_cgo_free
0004ea60 T x_cgo_init
0004eb24 T x_cgo_malloc
0004e8e0 T x_cgo_notify_runtime_init_done
0004eb14 T x_cgo_setenv
0004e820 T x_cgo_sys_thread_create
0004eb64 T x_cgo_thread_start
0004eb20 T x_cgo_unsetenv
像这样(在1.5.1 linux / arm上测试)
goc.go:
package main
import (
"C"
"fmt"
)
//export PrintInt
func PrintInt(x int) {
fmt.Println(x)
}
// http://stackoverflow.com/questions/32215509/using-go-code-in-an-existing-c-project
// go build -buildmode=c-archive goc.go
// go build -buildmode=c-shared goc.go
// https://groups.google.com/forum/#!topic/golang-nuts/1oELh6joLQg
// Trying it on windows/amd64, looks like it isn't supported yet. Is this planned for the 1.5 release?
// It will not be in the 1.5 release.
// It would be nice if somebody worked on it for 1.6.
// https://golang.org/s/execmodes
// http://stackoverflow.com/questions/19431296/building-and-linking-dynamically-from-a-go-binary
// go build -linkshared hello.g
// go install -buildmode=shared std
func main() {
fmt.Println("Hello world")
}
答案 4 :(得分:-1)
自1.5以来推荐的功能:) http://talks.golang.org/2015/state-of-go-may.slide#23