>  기사  >  백엔드 개발  >  golang이 php7을 호출하는 방법에 대해 이야기합시다.

golang이 php7을 호출하는 방법에 대해 이야기합시다.

藏色散人
藏色散人앞으로
2021-09-20 16:30:172403검색

이 글은 go 언어 튜토리얼 칼럼에서 golang에서 php7을 호출하는 방법을 소개하기 위해 쓴 글입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다!

을 호출합니다. https://github.com/taowen/go-php7
基于 https://github.com/deuill/go-php 修改而来,fork缘由(https://github.com/deuill/go-php/issues/32)

执行php文件

func Test_exec(t *testing.T) {
    engine.Initialize()
    ctx := &engine.Context{
        Output: os.Stdout,
    }
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    err = ctx.Exec("/tmp/index.php")
    if err != nil {
        fmt.Println(err)
    }
}

其中 /tmp/index.php 的内容为

<?php
echo("hello\n");

Eval,返回值

func Test_eval(t *testing.T) {
    engine.Initialize()
    ctx := &engine.Context{}
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    val, err := ctx.Eval("return &#39;hello&#39;;")
    if err != nil {
        fmt.Println(err)
    }
    defer engine.DestroyValue(val)
    if engine.ToString(val) != "hello" {
        t.FailNow()
    }
}

返回的value的生命周期所有权是golang程序,所以我们要负责DestroyValue

设置全局变量来传参

func Test_argument(t *testing.T) {
    engine.Initialize()
    ctx := &engine.Context{}
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    err = ctx.Bind("greeting", "hello")
    if err != nil {
        fmt.Println(err)
    }
    val, err := ctx.Eval("return $greeting;")
    if err != nil {
        fmt.Println(err)
    }
    defer engine.DestroyValue(val)
    if engine.ToString(val) != "hello" {
        t.FailNow()
    }
}

传递进去的参数的生命周期是php控制的,在request shutdown的时候内存会被释放。

PHP 回调 Golang

type greetingProvider struct {
    greeting string
}

func (provider *greetingProvider) GetGreeting() string {
    return provider.greeting
}

func newGreetingProvider(args []interface{}) interface{} {
    return &greetingProvider{
        greeting: args[0].(string),
    }
}

func Test_callback(t *testing.T) {
    engine.Initialize()
    ctx := &engine.Context{}
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    err = engine.Define("GreetingProvider", newGreetingProvider)
    if err != nil {
        fmt.Println(err)
    }
    val, err := ctx.Eval(`
    $greetingProvider = new GreetingProvider(&#39;hello&#39;);
    return $greetingProvider->GetGreeting();`)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.DestroyValue(val)
    if engine.ToString(val) != "hello" {
        t.FailNow()
    }
}

PHP 错误日志

func Test_log(t *testing.T) {
    engine.PHP_INI_PATH_OVERRIDE = "/tmp/php.ini"
    engine.Initialize()
    ctx := &engine.Context{
        Log: os.Stderr,
    }
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    _, err = ctx.Eval("error_log('hello', 4); trigger_error('sent from golang', E_USER_ERROR);")
    if err != nil {
        fmt.Println(err)
    }
}

其中 /tmp/php.ini 的内容为

error_reporting = E_ALL
error_log = "/tmp/php-error.log"

错误会被输出到 /tmp/php-error.log。直接调用error_log会同时再输出一份到stderr

HTTP 输入输出

func Test_http(t *testing.T) {
    engine.Initialize()
    recorder := httptest.NewRecorder()
    ctx := &engine.Context{
        Request: httptest.NewRequest("GET", "/hello", nil),
        ResponseWriter: recorder,
    }
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    _, err = ctx.Eval("echo($_SERVER['REQUEST_URI']);")
    if err != nil {
        fmt.Println(err)
    }
    body, err := ioutil.ReadAll(recorder.Result().Body)
    if err != nil {
        fmt.Println(err)
    }
    if string(body) != "/hello" {
        t.FailNow()
    }
}

所有的PHP超级全局变量都会被初始化为传递进去的Request的值,包括

$_SERVER
$_GET
$_POST
$_FILE
$_COOKIE
$_ENV

echo的内容,http code和http header会被写回到传入的ResponseWriter

fastcgi_finish_request

PHP-FPM 很常用的一个功能是fastcgi_finish_requesthttps://github.com/deuill/go-php를 기준으로 수정됨, 이유 포크용 (https://github.com/deuill/go-php/issues/32)

php 파일 실행

func Test_fastcgi_finish_reqeust(t *testing.T) {
    engine.Initialize()
    buffer := &bytes.Buffer{}
    ctx := &engine.Context{
        Output: buffer,
    }
    err := engine.RequestStartup(ctx)
    if err != nil {
        fmt.Println(err)
    }
    defer engine.RequestShutdown(ctx)
    ctx.Eval("ob_start(); echo ('hello');")
    if buffer.String() != "" {
        t.FailNow()
    }
    ctx.Eval("fastcgi_finish_request();")
    if buffer.String() != "hello" {
        t.FailNow()
    }
}

/tmp/index.php 내용

rrreee

Eval의 경우 반환 값

rrreee
반환된 값의 수명 주기 소유권은 golang 프로그램이므로 DestroyValue

매개 변수 전달을 위한 전역 변수 설정

rrreee는 우리가 담당합니다. pass it in 매개변수의 수명 주기는 PHP에 의해 제어되며, 요청이 종료되면 메모리가 해제됩니다.

PHP 콜백 Golang

rrreee

PHP 오류 로그

rrreee
/tmp/php.ini의 내용은 rrreee🎜오류가 다음으로 출력됩니다. /tmp/php-error.log. error_log를 직접 호출하면 stderr🎜

HTTP 입력 및 출력

rrreee🎜에 또 다른 복사본이 출력됩니다. 모든 PHP 슈퍼 전역 변수는 🎜rrreee🎜echo, http의 내용을 포함하여 전달된 요청 값으로 초기화됩니다. 코드와 http 헤더는 들어오는 ResponseWriter에 다시 기록됩니다🎜

fastcgi_finish_request

🎜PHP-FPM 매우 일반적으로 사용되는 함수는 fastcgi_finish_request이며, 이는 비동기 완료를 수행하는 데 사용됩니다. PHP 것들. 이 특별한 전역 함수는 🎜rrreee🎜를 지원해야 합니다. 실제 함수는 호출자가 결과를 알 수 있도록 미리 ResposneWriter에 출력을 출력하는 것입니다. 실제로 현재 프로세스의 실행에는 영향을 주지 않고 출력에만 영향을 줍니다. 🎜🎜🎜추천 학습: "🎜golang 튜토리얼🎜"🎜🎜

위 내용은 golang이 php7을 호출하는 방법에 대해 이야기합시다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 segmentfault.com에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제