我有一个Makfile稍微修改,以帮助更好地解释 case :

include $(wildcard .env)

DB_URL=postgres://$(POSTGRES_USER):$(POSTGRES_PASSWORD)@$(POSTGRES_HOST):$(POSTGRES_PORT)/$(POSTGRES_DB)?sslmode=disable&pool_max_conns=10

test:
    @echo $(DB_URL)
    @cat .env
    @-include .env
    @echo "Running tests"
    @DB=$(DB_URL) go test ./... -v -coverprofile=coverage.out

第一行显示了正在创建的正确的DB URL,因此它将按照预期导入.env文件.第二行也起作用.第三行显示以下错误:

make: include: No such file or directory
make: [test] Error 1 (ignored)

现在,虽然我可以看到我的DB URL存在,但我不明白为什么我看不到DB中的任何东西.go test表示DB为空字符串.如果我导出硬编码的DB URL,一切都按预期工作.

如果有人能帮我理解为什么会发生这种事就太好了.使用MacOS Sonoma.我一直在使用同一个Makefile几个星期,从来没有改变.env或Makefile,但这停止工作几个小时前.

推荐答案

在食谱之外,这…

include $(wildcard .env)

...是对make的指令.

在食谱里,这...

    @-include .env

是一个shell command,模@-,它禁止打印命令,并且不会在错误时终止配方. 但是include不是内置的shell,而且,不出所料,在可执行搜索路径中没有这样的命令,因此:

make: include: No such file or directory

你继续

现在,虽然我可以看到我的DB URL存在,但我不明白为什么我看不到DB中的任何东西.go test表示DB为空字符串.

你要小心引用. make$(DB_URL)扩展为以sslmode=disable&pool_max_conns=10结尾的字符串. &作为命令分隔符对shell很重要(这导致前面的命令作为后台作业(job)运行). 因此,是的,go test在其环境中不会看到DB的值,或者至少不会因为配方设置了一个值. 它将看到它的环境的唯一增加是pool_max_conns=10,你甚至不想让它得到.

如果URL包含其他对shell重要的字符,例如;$,可能会出现其他类似的问题. 只要URL不包含任何'个字符,你就可以这样做:

    DB='$(DB_URL)' go test ./... -v -coverprofile=coverage.out

附注:永远不要 suppress 命令回声在你的食谱,直到你sure他们工作正常. 也许那时也不会.

Go相关问答推荐

如何获得与cksum相同的CRC 32?

为什么工具链指令在这种情况下没有效果?

使用一元或服务器流将切片从GRPC服务器返回到客户端

是不是有什么原因导致`Strings.EqualFold`不先进行长度比较?

通过渠道和goroutines增值1000倍

go测试10m后如何避免超时

使用 goroutine 比较 Golang 中的两棵树是等价的

Gorm 在自定义字符串类型上返回 scanner 错误

获取 nil 指针类型的 reflect.Value

如何使用 go 包设置标头键和值:shurcooL/graphql 或 hasura/go-graphql-client?

Golang 中具体类型的错误片段

go:embed 文件扩展名模式

Golang计算 struct struct 中的字段数

函数超时和 goroutine 泄漏

为什么时间很短.睡眠时间比基准测试中要求的(约 300 ns)长?

gorm 获取列名

为什么 Go 中的 maps.Keys() 将 map 类型指定为 M?

有没有办法在golang中映射一组对象?

是否存在一个Go泛型类型约束,该约束捕获了将类型用作映射中的键的能力?

Go 1.18 泛型如何使用接口定义新的类型参数