英文:
golang os.Create cause "no such file or directory" error
问题
一定是有什么简单的问题,但我似乎无法弄清楚。我一直收到“没有这样的文件或目录”错误。我以为Create函数是用来创建新文件的?
package main
import (
"log"
"os"
)
func main() {
f, err := os.Create("~/golang-server.log")
defer f.Close()
if err != nil {
panic(err.Error())
}
log.SetOutput(f)
}
英文:
Must be something simple, but I cannot seem to figure out. I keep getting "no such file or directory" error. Thought the Create function is to create a new file?
package main
import (
"log"
"os"
)
func main() {
f, err := os.Create("~/golang-server.log")
defer f.Close()
if err != nil {
panic(err.Error())
}
log.SetOutput(f)
}
</details>
# 答案1
**得分**: 5
你不能使用`~`或环境变量(如`$HOME`)来指定文件路径,它们是字符串字面量,表示实际路径。你得到的错误是因为它将`~/golang-server.log`视为当前目录的相对路径,而当前目录中没有名为`~`的目录。
通过手动创建子目录`~`,你的代码将成功运行:
~/test/ mkdir \~
~/test/ go run t.go
~/test/ ls \~
golang-server.log
因此,需要传递一个`绝对路径`或`相对路径`给`os.Create`。
<details>
<summary>英文:</summary>
You can't use `~` or environment variable like `$HOME` to specify the file path, they're string literal and means actual path. The error you got is because it treat `~/golang-server.log` as a relative path of current directory, and there's no directory `~` in current directory.
With manually created sub-directory `~`, your code will succeed:
~/test/ mkdir \~
~/test/ go run t.go
~/test/ ls \~
golang-server.log
So need to pass an `absolute path` or `relative path` to `os.Create`.
</details>
# 答案2
**得分**: 4
你可以使用`os.ExpandEnv`来处理在sh/bash上下文中才有意义的"~"符号。
```go
os.Create(os.ExpandEnv("$HOME/golang-server.log"))
在更复杂的情况下,你需要确保基础目录存在,因为os.Create
不会处理它。
这就是为什么os.Create("~/golang-server.log")
会失败的原因,因为基础目录不存在,而os.Create
不会自动为你创建它。你需要像这样自己创建:
func EnsureBaseDir(fpath string) error {
baseDir := path.Dir(fpath)
info, err := os.Stat(baseDir)
if err == nil && info.IsDir() {
return nil
}
return os.MkdirAll(baseDir, 0755)
}
注意:
$HOME
并不总是存在,例如程序作为系统级别的systemd
服务运行。因此,在生产环境中最好不要使用$HOME
。os.Create
的限制不仅存在于Go中,它是由操作系统内核引起的,在其他语言/标准库中也广泛存在。
英文:
You can use os.ExpandEnv
to handle the "~" which is only make sense in sh/bash context.
os.Create(os.ExpandEnv("$HOME/golang-server.log"))
In more complicated cases, you need to ensure that the base directory exists, because os.Create
does not handle it.
And this is the reason why os.Create("~/golang-server.log")
will fail, because the base directory doesn't exist and os.Create
wouldn't automatically create it for you. You need do it by yourself like this:
func EnsureBaseDir(fpath string) error {
baseDir := path.Dir(fpath)
info, err := os.Stat(baseDir)
if err == nil && info.IsDir() {
return nil
}
return os.MkdirAll(baseDir, 0755)
}
NOTE:
$HOME
is not always exists, e.g. the program run as a system levelsystemd
service. So you better not use$HOME
in a production environment.- the limitation of
os.Create
doesn't only exist in Go. It's caused by the OS kernel and widely exists in other languages/stdlib.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论