在函数计算使用Go编程时,需要定义一个函数作为入口,您的代码将从此入口处开始执行。本文介绍Go事件函数的结构和特点。

事件函数示例

在Go语言的代码中,需要引入官方的SDK库github.com/aliyun/fc-runtime-go-sdk/fc,并且,需要实现handler函数和main函数。示例如下:

// hello_world.go
package main

import (
    "fmt"
    "github.com/aliyun/fc-runtime-go-sdk/fc"
)

func main() {
    fc.Start(HandleRequest)
}

func HandleRequest(event map[string]interface{}) (string, error) {
    fmt.Println("hello world")
    return "hello world", nil
}

事件函数入口

Go是编译型语言,需要在本地编译后直接上传可执行的二进制文件。在函数入口配置中,不同于Python和Node.js的[文件名].[函数名]格式,Go语言的函数入口可直接设置为[文件名]。该文件名是指编译后的二进制文件名称,当函数被调用时,函数计算平台会直接从函数入口配置的文件名开始执行。

handler函数参数及返回值定义

本文示例中的handler函数部分如下:

func HandleRequest(ctx context.Context, event map[string]interface{}) (string, error)

handler函数为您需执行的代码,主要包含以下内容:

  • ctx context.Context:运行时的信息,主要有RequestIDFunctionService等。必须放到第一个参数位置。详细信息,请参见context.go
  • event map[string]interface{}:事件信息,可以支持Go基本类型,以及Struct 类型,只能放到第二个参数位置。
  • (string, error):返回两个值,字符串和错误信息。其中第一个值支持Go基本类型,以及Struct类型。

handler支持的格式如下:

  • func ()
  • func () error
  • func (TIn) error
  • func () (TOut, error)
  • func (TIn) (TOut, error)
  • func (context.Context) error
  • func (context.Context, TIn) error
  • func (context.Context) (TOut, error)
  • func (context.Context, TIn) (TOut, error)

其中,TInTOutencoding/json标准库兼容。

event参数

注意 event类型为String时,传参必须是以双引号括起来的字符串。

如果参数为JSON,event可定义为Struct或Map,示例如下:

package main

import (
    "fmt"
    "github.com/aliyun/fc-runtime-go-sdk/fc"
)

func main() {
    fc.Start(HandleRequest)
}

func HandleRequest(event map[string]interface{}) (string, error) {
    fmt.Printf("event: %v\n", event)
    fmt.Println("hello world! 你好,世界!")
    return "hello world! 你好,世界!", nil
}

context参数

context包含的字段如下表所示。

字段 说明
变量
RequestID 本次调用请求的唯一ID。您可以记录该ID,当出现问题时方便查询。
Credentials 函数计算服务通过扮演服务角色而获取的一组临时密钥,其有效时间是5分钟。您可以在代码中使用Credentials去访问相应的服务例如OSS,这就避免了您把自己的AccessKey信息编码在函数代码里。详细信息,请参见通过RAM角色实现跨云账号授权
Function 当前调用的函数的一些基本信息,例如函数名、函数入口、函数内存和超时时间。
Service 当前调用的函数所在的服务信息,包含服务名称、接入的日志服务SLS的Project和Logstore信息,以及服务的版本和别名信息。其中qualifier表示调用函数时指定的服务版本或别名,version_id表示实际调用的服务版本。
Region 当前调用的函数所在地域ID,例如在华东2(上海)地域调用,则地域ID为cn-shanghai。详细信息,请参见服务地址
AccountId 当前调用函数用户的阿里云账号ID。
方法
deadline 返回函数执行的超时时间,格式为Unix时间戳,单位:毫秒。

使用示例

函数的handler需要包含context参数,把上述的变量信息插入到context的Value中。然后,需要import github.com/aliyun/fc-runtime-go-sdk/fccontext,通过fccontext.FromContext方法获取fccontext。具体示例如下:

package main

import (
    "context"
    "encoding/json"
    "log"    
    "github.com/aliyun/fc-runtime-go-sdk/fc"
    "github.com/aliyun/fc-runtime-go-sdk/fccontext"
)

func main() {
    fc.Start(echoContext)
}

func echoContext(ctx context.Context) (string, error) {
    fctx, _ := fccontext.FromContext(ctx)
    log.Println(fctx.AccountId)
    log.Printf("%#v\n", fctx)
    res, _ := json.Marshal(fctx)
    return string(res), nil
}

以下示例展示如何使用deadline获取函数剩余的执行时间。

package main

import (
    "context"
    "fmt"
    "log"
    "time"    
    "github.com/aliyun/fc-runtime-go-sdk/fc"
)

func LongRunningHandler(ctx context.Context) (string, error) {
    deadline, _ := ctx.Deadline()
    fmt.Printf("now: %s\ndeadline: %s\n", time.Now().String(), deadline.String())
    deadline = deadline.Add(-100 * time.Millisecond)
    timeoutChannel := time.After(time.Until(deadline))

    for {

        select {

        case <-timeoutChannel:
            return "Finished before timing out.", nil

        default:
            log.Print("hello!")
            time.Sleep(50 * time.Millisecond)
        }
    }
}

func main() {
    fc.Start(LongRunningHandler)
}