Python与Go结合

Python与Go结合的方法

Python和Go可以通过多种方式结合使用,通常采用跨语言通信或集成的方式。以下是几种常见的方法:

使用CFFI或CGO进行绑定

Python可以通过CFFI(C Foreign Function Interface)调用Go编写的库,而Go可以通过CGO导出函数供Python调用。这种方法需要将Go代码编译为动态链接库(.so或.dll文件),然后在Python中加载并调用。

在Go中编写并导出函数:

go 复制代码
package main

import "C"

//export Add
func Add(a, b int) int {
    return a + b
}

func main() {}

编译为动态库:

bash 复制代码
go build -buildmode=c-shared -o libadd.so add.go

在Python中使用CFFI调用:

python 复制代码
from cffi import FFI

ffi = FFI()
ffi.cdef("int Add(int a, int b);")
lib = ffi.dlopen("./libadd.so")

result = lib.Add(2, 3)
print(result)  # 输出5

使用gRPC进行通信

gRPC是一个高性能的远程过程调用框架,支持多种语言。可以在Go中实现gRPC服务端,在Python中实现客户端,或反之。

定义proto文件:

proto 复制代码
syntax = "proto3";

service Greeter {
    rpc SayHello (HelloRequest) returns (HelloReply) {}
}

message HelloRequest {
    string name = 1;
}

message HelloReply {
    string message = 2;
}

Go实现服务端:

go 复制代码
package main

import (
    "context"
    "log"
    "net"

    "google.golang.org/grpc"
    pb "path/to/your/proto"
)

type server struct{}

func (s *server) SayHello(ctx context.Context, in *pb.HelloRequest) (*pb.HelloReply, error) {
    return &pb.HelloReply{Message: "Hello " + in.Name}, nil
}

func main() {
    lis, err := net.Listen("tcp", ":50051")
    if err != nil {
        log.Fatalf("failed to listen: %v", err)
    }
    s := grpc.NewServer()
    pb.RegisterGreeterServer(s, &server{})
    s.Serve(lis)
}

Python实现客户端:

python 复制代码
import grpc
from proto import greeter_pb2, greeter_pb2_grpc

channel = grpc.insecure_channel('localhost:50051')
stub = greeter_pb2_grpc.GreeterStub(channel)
response = stub.SayHello(greeter_pb2.HelloRequest(name='World'))
print(response.message)  # 输出 "Hello World"

使用HTTP/REST API

Go可以提供一个HTTP服务,Python通过HTTP请求与之交互。这是最通用的方法之一。

Go实现HTTP服务:

go 复制代码
package main

import (
    "encoding/json"
    "net/http"
)

type Response struct {
    Message string `json:"message"`
}

func handler(w http.ResponseWriter, r *http.Request) {
    resp := Response{Message: "Hello from Go"}
    json.NewEncoder(w).Encode(resp)
}

func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
}

Python使用requests调用:

python 复制代码
import requests

response = requests.get("http://localhost:8080")
print(response.json())  # 输出 {"message": "Hello from Go"}

使用消息队列

通过消息队列(如RabbitMQ、Kafka)可以实现Python和Go之间的异步通信。Python作为生产者发送消息,Go作为消费者处理消息,或反之。

Python使用pika发送消息:

python 复制代码
import pika

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.queue_declare(queue='hello')
channel.basic_publish(exchange='', routing_key='hello', body='Hello from Python')
connection.close()

Go使用amqp接收消息:

go 复制代码
package main

import (
    "log"
    
    "github.com/streadway/amqp"
)

func main() {
    conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/")
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()

    ch, err := conn.Channel()
    if err != nil {
        log.Fatal(err)
    }
    defer ch.Close()

    q, err := ch.QueueDeclare("hello", false, false, false, false, nil)
    if err != nil {
        log.Fatal(err)
    }

    msgs, err := ch.Consume(q.Name, "", true, false, false, false, nil)
    if err != nil {
        log.Fatal(err)
    }

    for d := range msgs {
        log.Printf("Received a message: %s", d.Body)
    }
}

使用共享内存或文件

对于简单的数据交换,可以通过共享文件或内存实现。Python和Go都可以读写相同的文件或共享内存区域。

Python写入文件:

python 复制代码
with open("shared.txt", "w") as f:
    f.write("Hello from Python")

Go读取文件:

go 复制代码
package main

import (
    "fmt"
    "io/ioutil"
)

func main() {
    data, err := ioutil.ReadFile("shared.txt")
    if err != nil {
        fmt.Println("Error reading file:", err)
        return
    }
    fmt.Println(string(data))  // 输出 "Hello from Python"
}

这些方法各有优缺点,适用于不同的场景。CFFI/CGO适合高性能调用,gRPC适合复杂服务,HTTP/REST通用性强,消息队列适合异步处理,共享文件简单但效率较低。

相关推荐
sweet丶6 小时前
理解iOS中Protobuf:一个比JSON更好,但不是替代
ios·性能优化·架构
tealcwu13 小时前
【Unity实战】如何使用VS Code在真实iOS设备上调试 Unity应用
unity·游戏引擎·iphone
疯笔码良14 小时前
【IOS开发】Instruments 使用指南
ios·swift
疯笔码良16 小时前
【IOS开发】后台保活方案
ios·swift
hid7117136618 小时前
大型源码C# MES WPF CS/BS两套 1, 整体程序由WPF(c#)开发; 2,各个文...
iphone
吴Wu涛涛涛涛涛Tao19 小时前
从单体到子壳:一套「对标亿级 DAU App」的 iOS 架构实战 Demo
ios·架构
linweidong21 小时前
网易ios面试题及参考答案(上)
ios·cdn·进程状态·虚拟内存·raii·网络链路·dns系统
從南走到北2 天前
JAVA海外短剧国际版源码支持H5+Android+IOS
android·java·ios