GoPyLink
A lightweight Python & Go cross-language call framework for in-process communication.
Features
- Python Call Go - Python call Go functions, create Go type instances and invoke methods
- Go Call Python - Go call Python functions, create Python class instances and invoke methods
- Simple API - Minimal setup with intuitive interfaces
Limitations
GoPyLink is designed for data exchange only. All function parameters and return values must be plain data types (primitives, collections, structs with all fields public).
Channels, goroutines, functions and interface types (except any) are not supported as parameters or return values.
Installation
Go
go get github.com/ray4go/go-ray/gopylink
Python
pip install gopylink
Requires: Go 1.21+, Python 3.7+
C build environment is required, click to show installation commands.
# Ubuntu/Debian
sudo apt install build-essential
# CentOS/RHEL
sudo yum groupinstall "Development Tools"
# macOS
xcode-select --install
Python calling Go
1. Export Go Functions/Types
Create a lib.go file:
package main
import "github.com/ray4go/gopylink"
// Functions to export - all exported methods become callable from Python
type Functions struct{}
func (Functions) Hello(name string) string {
return "Hello " + name
}
func (Functions) Add(a, b int) int {
return a + b
}
// Classes to export - each method creates a new instance
type Classes struct{}
type Counter struct {
value int
}
func (Classes) Counter(initial int) *Counter {
return &Counter{value: initial}
}
func (c *Counter) Incr(n int) int {
c.value += n
return c.value
}
func (c *Counter) Value() int {
return c.value
}
func init() {
gopylink.Init(Functions{}, Classes{})
}
func main() {}
2. Build Go Shared Library
go build -buildmode=c-shared -o go.lib .
3. Call Go from Python
# main.py
import gopylink
# Load the Go library
lib = gopylink.load_go_lib("go.lib")
# Call Go functions
result = lib.func_call("Hello", "World")
print(result) # Output: Hello World
result = lib.func_call("Add", 10, 20)
print(result) # Output: 30
# Create Go type instance and call methods
counter = lib.new_type("Counter", 0)
print(counter.Incr(5)) # Output: 5
print(counter.Incr(3)) # Output: 8
print(counter.Value()) # Output: 8
Run the python script:
python main.py
Go calling Python
1. Export Python Functions/Classes
# main.py
import gopylink
@gopylink.export
def greet(name: str) -> str:
return f"Hi, {name}!"
@gopylink.export
def multiply(a, b):
return a * b
@gopylink.export
class Counter:
def __init__(self, initial=0):
self.value = initial
def incr(self, n):
self.value += n
return self.value
if __name__ == "__main__":
lib = gopylink.load_go_lib("go.lib")
lib.func_call("Start") # Start the Go logic
2. Call Python from Go
package main
import (
"fmt"
"github.com/ray4go/gopylink"
)
type functions struct{}
func (functions) Start() {
// Call Python function
result := gopylink.PythonFuncCall("greet", "Gopher")
val, err := result.Get()
fmt.Printf("greet: %v, err: %v\n", val, err) // Output: greet: Hello, Gopher!, err: <nil>
// Call with typed result
result = gopylink.PythonFuncCall("multiply", 6, 7)
product, err := gopylink.Get[int](result)
fmt.Printf("multiply: %v, err: %v\n", product, err) // Output: multiply: 42, err: <nil>
// Create Python class instance
cnt := gopylink.NewPythonClassInstance("Counter", 10)
defer cnt.Close()
res := cnt.MethodCall("incr", 5)
val, err = res.Get()
fmt.Printf("Counter.incr: %v, err: %v\n", val, err) // Output: Counter.incr: 15, err: <nil>
}
func init() {
gopylink.Init(functions{}, nil)
}
func main() {}
3. Build and Run
go build -buildmode=c-shared -o go.lib .
python main.py
Note that when calling Python from Go, the entry point remains the Python script. The Go shared library is loaded into the Python process, which then starts the Go logic.
API Reference
Python API
| Function | Description |
|---|---|
load_go_lib(path) |
Load a Go shared library |
lib.func_call(name, *args) |
Call a Go function by name |
lib.new_type(name, *args) |
Create a Go type instance |
@export |
Decorator to export Python function/class to Go |
Go API
| Function | Description |
|---|---|
Init(funcRegister, classRegister) |
Initialize and register Go functions/classes |
PythonFuncCall(name, args...) |
Call a Python function |
NewPythonClassInstance(name, args...) |
Create a Python class instance |
Get[T](result) |
Get typed result from Python call |
result.Get() |
Get result as (any, error) |
handle.MethodCall(name, args...) |
Call method on Python instance |
handle.Close() |
Release Python instance |
See Go API Reference for more details.
Type Conversion
Types are automatically converted via msgpack:
| Go Type | Python Type |
|---|---|
int, int64, etc. |
int |
float32, float64 |
float |
bool |
bool |
string |
str |
[]byte |
bytes |
| slice, array | list |
map |
dict |
struct |
dict |
nil |
None |
For detailed type conversion rules, see the Cross-Language Type Conversion Guide.
Thread Safety
GoPyLink operations are thread-safe. Multiple goroutines/threads can safely call cross-language functions concurrently.
Performance Notes
Go FFI has approximately 30ns overhead per call compared to native C/C++ FFI due to Go's virtual stack. This overhead is:
- Negligible for coarse-grained operations
- Significant for micro-calls requiring millions of invocations per second
Best Practices
Golang Parameter and return types
- Prefer concrete types (primitive types, composites, structs, and their pointers) over interface types for parameters
- Do not use interface types as return values except for
anytype.
Golang Error handling
Do not return error (as it is an interface) directly from Ray Task functon / Actor methods. Instead, return concrete
types to indicate errors (e.g., return int for error code), or just panic in your code.
When ObjectRef.GetAll() / ObjectRef.Getinto() / ray.GetN(obj) is called on a panic-ed task/actor, it will return an error.
You can use fmt.Printf("%+v", err) to print the error stack trace.
License
MIT
Metadata
Release files for gopylink 1.0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gopylink-1.0.2.tar.gz | 5.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gopylink-1.0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 12.1 kB
Release files / gopylink-1.0.2.tar.gz
| Download URL | gopylink-1.0.2.tar.gz |
|---|---|
| Size | 5.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
373a4bf9f35c05c075e4508745128079fe24dbddfd2c91720788610d5c981919
|
|
BLAKE2b-256 checksum How to use checksums |
12baea7ef31f943867125e58bb45fc85d77a1cc7ce97f2196c411868e13dfa37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 11, 2026.
Transparency logRelease files / gopylink-1.0.2-py3-none-any.whl
| Download URL | gopylink-1.0.2-py3-none-any.whl |
|---|---|
| Size | 6.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
edc2dfd52960f0780f6577af13969c1fc22a5ff4cba3ce2bf830800531985891
|
|
BLAKE2b-256 checksum How to use checksums |
972e522c5a04bc39005c95da24185dd6ee6994c286044f816c9d888edeb7922f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jan 11, 2026.
Transparency log