更新时间:2025-08-28 GMT+08:00
分享

开发Go事件函数

关于Go函数的接口定义以及SDK接口说明请参考Go函数开发概述

开发Go函数

登录已经安装了Go 1.x SDK的linux服务器,按照如下步骤进行编译和打包。(当前支持Ubuntu 14.04,Ubuntu 16.04,SuSE 11.3,SuSE 12.0,SuSE 12.1)

  1. 创建一个临时目录例如“/home/fssgo”,将FunctionGraph的Go RUNTIME SDK解压到新创建的目录,并开启go module开关,操作如下:

    $ mkdir -p /home/fssgo

    $ unzip functiongraph-go-runtime-sdk-1.0.1.zip -d /home/fssgo

    $ export GO111MODULE="on"

  2. 在目录“/home/fssgo”下生成go.mod文件,操作如下,以模块名为test为例:

    $ go mod init test

  3. 在目录“/home/fssgo”下编辑go.mod文件,添加加粗部分内容:

    module test
    
    go 1.24.5
    
    require (
        huaweicloud.com/go-runtime v0.0.0-00010101000000-000000000000
    )
    
    replace (
        huaweicloud.com/go-runtime => ./go-runtime
    )

  4. 在目录“/home/fssgo”下创建函数文件,并实现如下接口:

    func Handler(payload []byte, ctx context.RuntimeContext) (interface{}, error)

    其中payload为客户端请求的body数据,ctx为FunctionGraph提供的运行时上下文对象,具体提供的方法可以参考表19,以test.go为例:

    package main
    
    import (
        "fmt"
        "huaweicloud.com/go-runtime/go-api/context"
        "huaweicloud.com/go-runtime/pkg/runtime"
        "huaweicloud.com/go-runtime/events/apig"
        "huaweicloud.com/go-runtime/events/cts"
        "huaweicloud.com/go-runtime/events/dds"
        "huaweicloud.com/go-runtime/events/dis"
        "huaweicloud.com/go-runtime/events/kafka"
        "huaweicloud.com/go-runtime/events/lts"
        "huaweicloud.com/go-runtime/events/smn"
        "huaweicloud.com/go-runtime/events/timer"
        "encoding/json"
    )
    
    func ApigTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var apigEvent apig.APIGTriggerEvent
        err := json.Unmarshal(payload, &apigEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", apigEvent.String())
        apigResp := apig.APIGTriggerResponse{
           Body: apigEvent.String(),
           Headers: map[string]string {
              "content-type": "application/json",
           },
           StatusCode: 200,
        }
        return apigResp, nil
    }
    
    func CtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var ctsEvent cts.CTSTriggerEvent
        err := json.Unmarshal(payload, &ctsEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", ctsEvent.String())
        return "ok", nil
    }
    
    func DdsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var ddsEvent dds.DDSTriggerEvent
        err := json.Unmarshal(payload, &ddsEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", ddsEvent.String())
        return "ok", nil
    }
    
    func DisTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var disEvent dis.DISTriggerEvent
        err := json.Unmarshal(payload, &disEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", disEvent.String())
        return "ok", nil
    }
    
    func KafkaTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var kafkaEvent kafka.KAFKATriggerEvent
        err := json.Unmarshal(payload, &kafkaEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", kafkaEvent.String())
        return "ok", nil
    }
    
    func LtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var ltsEvent lts.LTSTriggerEvent
        err := json.Unmarshal(payload, &ltsEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", ltsEvent.String())
        return "ok", nil
    }
    
    func SmnTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var smnEvent smn.SMNTriggerEvent
        err := json.Unmarshal(payload, &smnEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", smnEvent.String())
        return "ok", nil
    }
    
    func TimerTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var timerEvent timer.TimerTriggerEvent
        err := json.Unmarshal(payload, &timerEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        return timerEvent.String(), nil
    }
    
    func main() {
        runtime.Register(ApigTest)
    }

    约束与限制:

    1. 如果函数返回的error参数不是nil,则会认为函数执行失败。
    2. 如果函数返回的error为nil,FunctionGraph仅支持返回如下几种类型的值。

      nil:返回的HTTP响应Body为空。

      []byte:返回的HTTP响应Body内容为该字节数组内容。

      string:返回的HTTP响应Body内容为该字符串内容。

      其它:FunctionGraph会将返回值作为对象进行json编码,并将编码后的内容作为HTTP响应的Body,同时设置响应的"Content-Type"头为"application/json"。

    3. 上述例子使用APIG触发器的事件类型,如需使用其他触发器类型需要修改main函数的内容,例如使用CTS触发器则修改为runtime.Register(CtsTest),目前只支持注册一个入口
    4. 当函数的事件源是APIG时,相关约束条件请参考Base64解码和返回结构体的说明

  5. 编译和打包

    函数代码编译完成后,按照如下方式编译和打包。

    1. 编译

      $ cd /home/fssgo

      $ go build -o handler test.go

      “handler”作为函数执行入口可自定义,在FunctionGraph控制台的函数详情页设置中,可自行修改函数执行入口。

    2. 打包:

      $ zip fss_examples_go1.x.zip handler

  6. 创建函数

    登录函数工作流控制台,创建Go1.x函数,上传代码包fss_examples_go1.x.zip

    对于Go runtime,必须在编译之后打zip包,编译后的文件名称必须与函数执行入口的名称保持一致,例如:二进制文件名为handler,则“函数执行入口”命名为handler,Handler与步骤1中定义的函数保持一致。

  7. 测试函数

    1. 创建测试事件

      在函数详情页,单击“配置测试事件”,弹出“配置测试事件”页,输入测试信息如图1所示,单击“创建”。

      图1 配置测试事件
    2. 在函数详情页,选择已配置测试事件,单击“测试”,参考函数执行结果查看函数执行结果。

  1. 创建一个临时目录例如“/home/fssgo/src/huaweicloud.com”,将FunctionGraph的sdk Go RUNTIME SDK解压到新创建的目录,操作如下:

    $ mkdir -p /home/fssgo/src/huaweicloud.com

    $ unzip functiongraph-go-runtime-sdk-1.0.1.zip -d /home/fssgo/src/huaweicloud.com

  2. 在目录“/home/fssgo/src”下创建函数文件,并实现如下接口:

    func Handler(payload []byte, ctx context.RuntimeContext) (interface{}, error)

    其中payload为客户端请求的body数据,ctx为FunctionGraph提供的运行时上下文对象,具体提供的方法可以参考SDK接口,以test.go为例:

    package main
    
    import (
        "fmt"
        "huaweicloud.com/go-runtime/go-api/context"
        "huaweicloud.com/go-runtime/pkg/runtime"
        "huaweicloud.com/go-runtime/events/apig"
        "huaweicloud.com/go-runtime/events/cts"
        "huaweicloud.com/go-runtime/events/dds"
        "huaweicloud.com/go-runtime/events/dis"
        "huaweicloud.com/go-runtime/events/kafka"
        "huaweicloud.com/go-runtime/events/lts"
        "huaweicloud.com/go-runtime/events/smn"
        "huaweicloud.com/go-runtime/events/timer"
        "encoding/json"
    )
    
    func ApigTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var apigEvent apig.APIGTriggerEvent
        err := json.Unmarshal(payload, &apigEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", apigEvent.String())
        apigResp := apig.APIGTriggerResponse{
           Body: apigEvent.String(),
           Headers: map[string]string {
              "content-type": "application/json",
           },
           StatusCode: 200,
        }
        return apigResp, nil
    }
    
    func CtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var ctsEvent cts.CTSTriggerEvent
        err := json.Unmarshal(payload, &ctsEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", ctsEvent.String())
        return "ok", nil
    }
    
    func DdsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var ddsEvent dds.DDSTriggerEvent
        err := json.Unmarshal(payload, &ddsEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", ddsEvent.String())
        return "ok", nil
    }
    
    func DisTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var disEvent dis.DISTriggerEvent
        err := json.Unmarshal(payload, &disEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", disEvent.String())
        return "ok", nil
    }
    
    func KafkaTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var kafkaEvent kafka.KAFKATriggerEvent
        err := json.Unmarshal(payload, &kafkaEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", kafkaEvent.String())
        return "ok", nil
    }
    
    func LtsTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var ltsEvent lts.LTSTriggerEvent
        err := json.Unmarshal(payload, &ltsEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", ltsEvent.String())
        return "ok", nil
    }
    
    func SmnTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var smnEvent smn.SMNTriggerEvent
        err := json.Unmarshal(payload, &smnEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        ctx.GetLogger().Logf("payload:%s", smnEvent.String())
        return "ok", nil
    }
    
    func TimerTest(payload []byte, ctx context.RuntimeContext) (interface{}, error) {
        var timerEvent timer.TimerTriggerEvent
        err := json.Unmarshal(payload, &timerEvent)
        if err != nil {
           fmt.Println("Unmarshal failed")
           return "invalid data", err
        }
        return timerEvent.String(), nil
    }
    
    func main() {
        runtime.Register(ApigTest)
    }

    约束与限制:

    1. 如果函数返回的error参数不是nil,则会认为函数执行失败。
    2. 如果函数返回的error为nil,FunctionGraph仅支持返回如下几种类型的值。

      nil:返回的HTTP响应Body为空。

      []byte:返回的HTTP响应Body内容为该字节数组内容。

      string:返回的HTTP响应Body内容为该字符串内容。

      其它:FunctionGraph会将返回值作为对象进行json编码,并将编码后的内容作为HTTP响应的Body,同时设置响应的"Content-Type"头为"application/json"。

    3. 上述例子使用APIG触发器的事件类型,如需使用其他触发器类型需要修改main函数的内容,例如使用CTS触发器则修改为runtime.Register(CtsTest),目前只支持注册一个入口
    4. 当函数的事件源是APIG时,相关约束条件请参考Base64解码和返回结构体的说明

  3. 编译和打包

    函数代码编译完成后,按照如下方式编译和打包。

    1. 设置GOROOT和GOPATH环境变量:

      $ export GOROOT=/usr/local/go (假设Go安装到了/usr/local/go目录)

      $ export PATH=$GOROOT/bin:$PATH

      $ export GOPATH=/home/fssgo

    2. 编译:

      $ cd /home/fssgo

      $ go build -o handler test.go

      “handler”作为函数执行入口可自定义,在FunctionGraph控制台的函数详情页设置中,可自行修改函数执行入口。

    3. 打包:

      $ zip fss_examples_go1.x.zip handler

  4. 创建函数

    登录函数工作流控制台,创建Go1.x函数,上传代码包fss_examples_go1.x.zip

    对于Go runtime,必须在编译之后打zip包,编译后的文件名称必须与函数执行入口的名称保持一致,例如:二进制文件名为handler,则“函数执行入口”命名为handler,Handler与步骤1中定义的函数保持一致。

  5. 测试函数

    1. 创建测试事件。

      在函数详情页,单击“配置测试事件”,弹出“配置测试事件”页,输入测试信息如图2所示,单击“创建”。

      图2 配置测试事件
    2. 在函数详情页,选择已配置测试事件,单击“测试”,参考函数执行结果查看函数执行结果。

函数执行结果

执行结果由3部分组成:函数返回、执行摘要和日志。

表1 执行结果说明

参数项

执行成功

执行失败

函数返回

返回函数中定义的返回信息。

返回包含错误信息和错误类型的JSON文件。格式如下:

{
    "errorMessage": "", 
    "errorType":"", 
}

errorMessage:Runtime返回的错误信息

errorType:错误类型

执行摘要

显示请求ID、配置内存、执行时长、实际使用内存和收费时长。

显示请求ID、配置内存、执行时长、实际使用内存和收费时长。

日志

打印函数日志,最多显示4KB的日志。

打印报错信息,最多显示4KB的日志。

相关文档