我想編譯並運行go代碼作爲Postgresql存儲過程。 我的動機是因爲PostgreSQL可以用C語言編寫golang excensions可以被編譯爲c-共享Golang過程語言Postgresql
所以我要文件,pl.go:
package main
/*
#cgo CFLAGS: -Wall -Wpointer-arith -Wno-declaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fpic -I. -I./ -I/usr/include/postgresql/server -I/usr/include/postgresql/internal -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE -I/usr/include/libxml2
#cgo LDFLAGS: -Wall -Wmissing-prototypes -Wpointer-arith -Wdeclaration-after-statement -Wendif-labels -Wmissing-format-attribute -Wformat-security -fno-strict-aliasing -fwrapv -fexcess-precision=standard -march=x86-64 -mtune=generic -O2 -pipe -fstack-protector-strong -fpic -L/usr/lib -Wl,-O1,--sort-common,--as-needed,-z,relro -Wl,--as-needed -Wl,-rpath,'/usr/lib',--enable-new-dtags -shared
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
#ifdef PG_MODULE_MAGIC
PG_MODULE_MAGIC;
#endif
//the return value must be allocated trough palloc
void* ret(void *val, uint64 *size) {
void *retDatum = palloc(*size);
memcpy(retDatum, val, *size);
return retDatum;
}
PG_FUNCTION_INFO_V1(plgo_func);
*/
import "C"
import "unsafe"
func main() {}
//PGVal returns the Postgresql C type from Golang type (currently implements just stringtotext)
func PGVal(val interface{}) (ret interface{}) {
var size uintptr
switch v := val.(type) {
case string:
ret = C.cstring_to_text(C.CString(v))
size = unsafe.Sizeof(ret)
default:
ret = val
size = unsafe.Sizeof(ret)
}
return C.ret(ret, (*C.uint64)(unsafe.Pointer(size)))
}
的CFLAGS
和LDFLAGS
i'we了從pg_config
,並在那裏我創建函數來調用該文件,plgo.go:
package main
/*
#include "postgres.h"
#include "fmgr.h"
#include "utils/builtins.h"
*/
import "C"
//export plgo_func
func plgo_func(fcinfo *C.FunctionCallInfoData) interface{} {
return PGVal("meh")
}
共享庫與創建:go build -buildmode=c-shared -o plgo.so plgo.go pl.go && sudo cp plgo.so /usr/lib/postgresql
PostgreSQL中的功能與創建:
CREATE OR REPLACE FUNCTION public.plgo_func(integer)
RETURNS text AS
'$libdir/plgo', 'plgo_func'
LANGUAGE c IMMUTABLE STRICT
COST 1;
但是當我運行:psql -U root -d meh -c "select plgo_func(0)"
服務器崩潰有:
server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
connection to server was lost
編輯:我已經成功創建了golang「庫」,用於在golang中創建存儲過程和觸發器plgo :)
C沒有任何Go接口{}的概念。您需要從導出的函數中返回一個C類型。 (如果這不起作用,您需要從服務器獲得更多調試信息,以瞭解它爲什麼崩潰) – JimB
這沒有奏效,我該如何在該代碼中添加一些調試/日誌? '導入「日誌」'而不是打印到文件不起作用... – microo8
我想你是'ret'函數中的segfaulting,因爲'cstring_to_text'返回一個'* text',而你只有palloc該指針的大小,然後將'text'結構複製到該位置。我會首先在C語言中做一個概念驗證,以確保在擴展到Go/cgo之前可以完成這個工作。 – JimB