本文目录导读:

PHP 和 Go 是两种不同的编程语言,Go 调用 PHP 通常有两种场景:Go 代码中调用 PHP 脚本,或者 Go 程序通过 HTTP 请求调用 PHP 服务,以下是几种常见的方法:
通过命令行调用 PHP(最直接)
PHP 已安装且可执行文件在 PATH 中,可以使用 exec 或 os/exec 调用:
package main
import (
"fmt"
"os/exec"
"strings"
)
func main() {
// 简单调用 PHP 脚本
cmd := exec.Command("php", "-r", `echo "Hello from PHP!";`)
output, err := cmd.Output()
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(output))
// 调用 PHP 文件
cmd = exec.Command("php", "/path/to/your/script.php")
output, err = cmd.Output()
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(output))
// 带参数调用
cmd = exec.Command("php", "/path/to/your/script.php", "arg1", "arg2")
output, err = cmd.Output()
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(output))
}
PHP 脚本示例 (script.php):
<?php // 接收命令行参数 $arg1 = $argv[1] ?? 'default1'; $arg2 = $argv[2] ?? 'default2'; echo "Argument 1: $arg1, Argument 2: $arg2\n"; // 输出 JSON 结果 $result = ['name' => 'John', 'age' => 30]; echo json_encode($result); ?>
// Go 中解析 JSON 结果
var data map[string]interface{}
if err := json.Unmarshal(output, &data); err != nil {
fmt.Println("JSON parse error:", err)
return
}
fmt.Printf("Name: %s, Age: %v\n", data["name"], data["age"])
通过 HTTP 调用 PHP 服务(推荐)
最常见的做法是通过 HTTP/REST API 调用 PHP Web 服务:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
"time"
)
func main() {
// GET 请求
resp, err := http.Get("http://localhost:8080/api/users?name=John")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println("GET Response:", string(body))
// POST 请求
postData := map[string]interface{}{
"name": "John",
"email": "john@example.com",
}
jsonData, _ := json.Marshal(postData)
resp, err = http.Post("http://localhost:8080/api/users",
"application/json",
bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ = ioutil.ReadAll(resp.Body)
fmt.Println("POST Response:", string(body))
}
PHP REST API 示例 (api.php):
<?php
header('Content-Type: application/json');
switch ($_SERVER['REQUEST_METHOD']) {
case 'GET':
// 处理 GET 请求
$name = $_GET['name'] ?? 'Guest';
echo json_encode(['message' => "Hello, $name!"]);
break;
case 'POST':
// 处理 POST 请求
$input = json_decode(file_get_contents('php://input'), true);
echo json_encode(['received' => $input, 'status' => 'success']);
break;
default:
http_response_code(405);
echo json_encode(['error' => 'Method not allowed']);
}
?>
使用 PHP-FPM (FastCGI) 协议
对于更高效的调用,可以使用 FastCGI 协议:
package main
import (
"fmt"
"github.com/yookoala/gofast"
"net"
)
func main() {
// 连接到 PHP-FPM
conn, err := net.Dial("tcp", "127.0.0.1:9000")
if err != nil {
fmt.Println("Error:", err)
return
}
defer conn.Close()
// 创建 FastCGI 客户端
client := gofast.NewClient(conn)
// 调用 PHP 脚本
response, err := client.Request(
gofast.NewRequest(),
"127.0.0.1:9000",
"/path/to/script.php",
nil, // 请求参数
)
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println(string(response))
}
使用消息队列(异步调用)
适合异步处理场景:
package main
import (
"fmt"
"github.com/streadway/amqp"
)
func main() {
// 连接到 RabbitMQ
conn, _ := amqp.Dial("amqp://guest:guest@localhost:5672/")
defer conn.Close()
ch, _ := conn.Channel()
defer ch.Close()
q, _ := ch.QueueDeclare("php_tasks", false, false, false, false, nil)
// 发送消息给 PHP 消费者
body := `{"action": "process_data", "data": "some data"}`
err := ch.Publish("", q.Name, false, false, amqp.Publishing{
ContentType: "application/json",
Body: []byte(body),
})
if err != nil {
fmt.Println("Error:", err)
return
}
fmt.Println("Message sent to PHP worker")
}
使用 PHP 内置服务器(开发环境)
package main
import (
"fmt"
"net/http"
"os/exec"
"time"
)
func main() {
// 启动 PHP 内置服务器
cmd := exec.Command("php", "-S", "127.0.0.1:8080", "-t", "/path/to/php/directory")
cmd.Start()
defer cmd.Process.Kill()
// 等待服务器启动
time.Sleep(2 * time.Second)
// 调用 PHP 服务
resp, err := http.Get("http://127.0.0.1:8080/index.php")
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
fmt.Println("PHP server response:", resp.Status)
}
最佳实践建议
- HTTP API 方式:推荐用于生产环境,解耦性好,分布式支持
- 命令行方式:适合简单的数据处理或脚本执行
- 异步消息:适合耗时任务或批处理
- 性能考虑:如果是高性能要求,建议用 Go 重写 PHP 逻辑,或使用 gRPC
选择哪种方式取决于你的具体需求、性能要求和部署环境,大多数情况下,HTTP REST API 是最通用和可维护的方案。