【问题标题】:Gcloud functions deployment doesn't find Golang template filesGcloud 函数部署找不到 Golang 模板文件
【发布时间】:2020-06-16 13:14:02
【问题描述】:

我编写了一些 Golang 代码,在我的本地机器上测试时可以使用。当我将其部署为 Google Cloud 功能时,它会失败,因为它无法打开模板文件。失败的代码行是:

    t, err := template.New("list.gohtml").ParseFiles("list.gohtml")

在此调用之后,err 设置为 open list.gohtml: no such file or directory

该文件与 go 源文件在同一目录下,并且未列在 .gcloudignore.gitignore 中。 gcloud 函数文档说,除非在其中一个忽略文件中列出,否则目录中的所有文件都将被上传,如果我运行 gcloud meta list-files-for-upload,则文件 list.gohtml 包含在显示的列表中。 p>

是否有一些神奇的文件夹布局可以完成这项工作,或者gcloud functions deploy 命令的选项?

【问题讨论】:

    标签: go google-cloud-functions gcloud go-templates


    【解决方案1】:

    我创建了一个枚举上传文件的函数:

    func L(w http.ResponseWriter, r *http.Request) {
        var files []string
    
        err := filepath.Walk(".", func(path string, info os.FileInfo, err error) error {
            files = append(files, path)
            return nil
        })
        if err != nil {
            panic(err)
        }
        for _, file := range files {
            fmt.Fprintln(w, file)
        }
    }
    
    

    输出:

    .
    go.mod
    go.sum
    main.go
    serverless_function_source_code
    serverless_function_source_code/f.go
    serverless_function_source_code/go.mod
    serverless_function_source_code/test.tmpl
    

    重写模板使用函数:

    tmpl, err := template.New("test.tmpl").ParseFiles("serverless_function_source_code/test.tmpl")
    

    有效!

    但是,这是无证的,而且是 hack :-(

    另一种方法是将模板作为字符串嵌入到 Golang 文件中。

    我建议在 Google 的问题跟踪器上为 Cloud Functions 提交功能请求

    【讨论】:

    • 谢谢 - 检查文件树将是我的下一步。我已经获取了您的信息并创建了自己的解决方案。在程序中嵌入模板会使开发变得痛苦,因此这不是一个好的解决方案,但我可能会考虑模板的后台加载和缓存以加快函数响应。
    • 其实原来是那个目录is documented
    【解决方案2】:

    根据@DazWilkin 的回复,我现在在服务函数的开头调用下面的函数。

    而不是将路径硬连接到模板文件名中(这会在本地测试时失败),这只是检查当前文件下方是否存在Gcloud source file directory,如果存在,则使其成为工作目录,因此文件解析现在将与在本地测试时完全相同。

    import "os"
    
    const gcloudFuncSourceDir = "serverless_function_source_code"
    
    func fixDir() {
        fileInfo, err := os.Stat(gcloudFuncSourceDir)
        if err == nil && fileInfo.IsDir() {
            _ = os.Chdir(gcloudFuncSourceDir)
        }
    }
    

    【讨论】:

      【解决方案3】:

      如果没有go.mod 文件(换句话说,如果未启用模块),则行为会发生变化并且文件位于src/<package-name>/ 下,而不是serverless_function_source_code/ 下。用于驱动云功能的main.go文件位于src/serverless_function_app/main/main.go

      例如:

      我有一个包含以下两个文件的 Go 应用程序:

      listfiles/file_system.go
      listfiles/tmpl/letter.html
      

      我使用以下命令部署它:

      cd listfiles
      gcloud functions deploy ListFiles --runtime go113 --trigger-http --allow-unauthenticated
      

      结果是当前目录设置为/srv。在/srv 下方是一个典型的GOROOT 树,其中包含src/pkg/ 目录。例如:

      .googlebuild
      .googlebuild/source-code.tar.gz
      pkg
      pkg/linux_amd64
      pkg/linux_amd64/github.com
      pkg/linux_amd64/github.com/GoogleCloudPlatform
      pkg/linux_amd64/github.com/GoogleCloudPlatform/functions-framework-go
      pkg/linux_amd64/github.com/GoogleCloudPlatform/functions-framework-go/funcframework.a
      src
      src/cloud.google.com
      src/cloud.google.com/go
      src/cloud.google.com/go/.git
      src/cloud.google.com/go/.git/HEAD
      src/cloud.google.com/go/.git/branches
      [... snip...]
      src/go.uber.org/zap/zaptest/testingt_test.go
      src/go.uber.org/zap/zaptest/timeout.go
      src/go.uber.org/zap/zaptest/timeout_test.go
      src/go.uber.org/zap/zaptest/writer.go
      src/go.uber.org/zap/zaptest/writer_test.go
      src/listfiles
      src/listfiles/file_system.go
      src/listfiles/tmpl
      src/listfiles/tmpl/letter.html
      src/serverless_function_app
      src/serverless_function_app/main
      src/serverless_function_app/main/main.go
      

      【讨论】:

        猜你喜欢
        • 2020-06-09
        • 2022-01-11
        • 1970-01-01
        • 2014-11-27
        • 1970-01-01
        • 1970-01-01
        • 2020-04-27
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多