Golang中如何简单地将字符串和变量写入文件
Golang中如何简单地将字符串和变量写入文件 我一直在学习Go by Example网站上的教程,但感觉有些吃力。
在写入文件之前,我是否需要为要写入的内容创建缓冲区?我发现了太多创建文件和写入文件的方法,以至于不太确定实际发生了什么过程。
如果有人能提供一些简单的Python到Golang的对比示例供我学习和讨论,我将不胜感激。
谢谢
如何写入一个没有内容的文件(缓冲区)?
更多关于Golang中如何简单地将字符串和变量写入文件的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
缓冲仅在需要写入大量数据时才需要使用。你说的缓冲概念具体指什么?我可以帮你解答。
老实说我不太确定该从哪里开始。您是否有关于使用缓冲区的相关资料或链接?另外,什么时候应该使用缓冲区呢?
谢谢
感谢两位的代码审查。另外,@inancgumus 感谢您展示的“缓冲区”示例,这不仅让我持续思考缓冲区的概念,而且获得两个不同版本对我非常有帮助。
RR
我有点困惑——我以为我通过以下代码行将’c’的输出转换为字符串并将新类型保存到’g’:
g := string([]byte(c[:]))
老实说我不太确定。作为缓冲区概念的新手,之前在TCL和Perl中可以直接将变量/标量写入文件句柄。
但我希望在Go中找到类似的功能,能够直接将变量写入文件句柄,而无需考虑缓冲区及其存储的字节数。
这样
import "os/exec"
并不会同时导入 os。你必须添加
import "os"
此外,我想说的是——如果您能详细讲解缓冲区的概念及相关原理……我会很乐意学习缓冲区的工作原理,并在编程中运用更好的方法解决问题。
我找到了一个链接,但它不仅限于Go语言,因为缓冲是一个通用的计算机科学/编程概念:https://www.quora.com/In-C-what-does-buffering-I-O-or-buffered-I-O-mean/answer/Robert-Love-1
这证实了我之前告诉你的内容(请参阅我上面关于bufio的解释)。缓冲区主要用于提高效率。
package main
import (
"fmt"
"os/exec"
//"io"
)
func main() {
c,_ := exec.Command("ping","-n","1","8.8.8.8").CombinedOutput()
//fmt.Printf("%s",c)
f, _ := os.Create("./output.txt")
defer f.Close()
ln, _ := f.WriteString(c)
fmt.Printf("%s",ln)
}
不确定为什么我会收到
undefined: os
另外,我阅读了你提供的链接,同时开始查找一些C语言文档,以便学习关于缓冲区的知识。
谢谢
func main() {
fmt.Println("hello world")
}
您好 Inancgumus, 感谢您提供的这个示例 - 这让我对Go语言中将字符串写入文件的代码概念有了更清晰的理解;不过,您能否展示一个使用缓冲区概念的简单写入示例,这样我就能开始用更好的编程概念和技能来思考了?
我仍然感觉自己在概念理解上有所欠缺,这些概念通常我不会想到,或者是隐藏在背景中的概念。我正在学习Manning出版社William Kennedy所著的《Go实战》一书,但进展缓慢,而我正渴望能更深入地沉浸到Go语言中。
谢谢 RR
我不太明白你想解释什么,但这样做是没必要的:
g := string([]byte(c[:]))
这是因为 c 是一个字节切片([]byte)。所以,直接这样做就足够了:
g := string(c)
但你其实也不需要这样做。f 有一个 Write 方法,它期望接收 []byte 参数,所以你可以直接这样调用:
c, _ := exec.Command("ping", "-n", "1", "8.8.8.8").CombinedOutput()
f, _ := os.Create("./output.txt")
defer f.Close()
ln, _ := f.Write(c)
fmt.Printf("%d", ln)
不过,我还是建议你使用我之前某条消息中发给你的代码。
让我们来看一下 gobyexample 中的示例:
-
ioutil.WriteFile适用于一次性写入文件的情况- 它会创建或截断文件(无法追加内容)
-
os.Create类似于os.OpenFile- 它会创建文件,如果文件已存在则截断,并返回文件句柄
- 在底层它会调用
OpenFile,如下所示:
OpenFile(filename, O_RDWR|O_CREATE|O_TRUNC, 0666)
-
f.Write用于通过字节切片向文件写入内容 -
f.WriteString用于通过字符串值向文件写入内容 -
bufio.NewWriter用于需要高效连续写入文件的情况- 这是因为它会缓冲你的
Write调用(在内存中缓冲),然后在某个时间点将累积的缓冲区实际写入文件。所以它不会每次写入都执行磁盘操作,而是批量写入
- 这是因为它会缓冲你的
实际上,你可以像在 Perl 中那样在 Go 中实现相同的功能。要做到这一点,你需要先打开文件以获取文件句柄,如下所示(这实际上与 go by example 网站上的示例几乎相同):
f, err := os.OpenFile(file, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
panic(err) // 这里我简化了处理。你可以根据需求自行处理错误。
}
defer f.Close()
然后,你可以像这样直接向文件写入字符串:
f.WriteString("hello world")
f.WriteString("what's up?")
你甚至可以向文件句柄写入格式化消息,如下所示:
fmt.Fprintf(f, "my age is %d\n", 95)
补充说明: 请务必阅读此链接中的文章。
可以按如下方式实现相同功能:
在这个示例中,我将命令的标准输出重定向到我的文件句柄:f。
package main
import (
"log"
"os"
"os/exec"
)
func main() {
f, _ := os.Create("./output.txt")
defer f.Close()
c := exec.Command("ping", "-c", "1", "-n", "8.8.8.8")
c.Stdout = f
if err := c.Run(); err != nil {
log.Fatal(err)
}
}
例如,当命令产生大量输出时,这就是需要使用缓冲的场景之一。你可以轻松地这样实现:
package main
import (
"bufio"
"log"
"os"
"os/exec"
)
func main() {
f, _ := os.Create("./output.txt")
defer f.Close()
buffered := bufio.NewWriter(f)
c := exec.Command("ping", "-c", "1", "-n", "8.8.8.8")
c.Stdout = buffered
if err := c.Run(); err != nil {
log.Fatal(err)
}
if err := buffered.Flush(); err != nil {
log.Fatal(err)
}
}
您的解决方案有效,但我还想继续尝试。
我在实验代码时开始尝试不同的方法,以便学习和理解这里发生的情况。从简单的开始,尝试理解返回对象的类型。为此,我使用了以下代码:
fmt.Printf("%T\n",g)
我注意到返回的结果是"[]uint8",这出乎我的意料。后来我在另一个在线论坛找到了这段代码:
:= string([]byte(c[:]))
根据我的研究,"c"是作为字节数组返回的(不确定"数组"这个词是否准确);但我意识到需要将[]uint8转换为字符串,上面的代码实现了这个功能。
我目前的代码如下:
package main
import (
"fmt"
"os/exec"
//"io"
"os"
)
func main() {
//var c string
c, _ := exec.Command("ping","-n","1","8.8.8.8").CombinedOutput()
fmt.Printf("%T\n", c)
g := string([]byte(c[:]))
fmt.Printf("%T\n",g)
//fmt.Printf("%s",c)
//g := string(c)
f, _ := os.Create("./output.txt")
defer f.Close()
ln, _ := f.WriteString(g)
fmt.Printf("%s",ln)
}
代码似乎可以工作;但我在命令提示符中收到以下输出:
%!s(int=280)
我不确定这个输出是从哪里来的,或者它是如何生成的。是什么导致了这种输出?
在Go语言中,将字符串和变量写入文件有多种直接的方法,无需显式创建缓冲区。以下是几种常见的方式,与Python进行对比,帮助你理解。
1. 使用 os.WriteFile 一次性写入(类似Python的 write 方法)
这种方法简单直接,适用于一次性写入整个字符串或字节数据。
Python示例:
content = "Hello, World!\n"
with open("output.txt", "w") as f:
f.write(content)
Go示例:
package main
import "os"
func main() {
content := "Hello, World!\n"
err := os.WriteFile("output.txt", []byte(content), 0644)
if err != nil {
panic(err)
}
}
os.WriteFile直接写入字节切片,自动处理文件创建和关闭。- 权限
0644表示文件可读写(所有者),只读(其他用户)。
2. 使用 os.Create 和 fmt.Fprintf 写入格式化变量(类似Python的 open 和格式化字符串)
适用于需要格式化输出变量或多次写入的情况。
Python示例:
name = "Alice"
age = 30
with open("output.txt", "w") as f:
f.write(f"Name: {name}, Age: {age}\n")
Go示例:
package main
import (
"fmt"
"os"
)
func main() {
name := "Alice"
age := 30
file, err := os.Create("output.txt")
if err != nil {
panic(err)
}
defer file.Close()
_, err = fmt.Fprintf(file, "Name: %s, Age: %d\n", name, age)
if err != nil {
panic(err)
}
}
os.Create创建或截断文件,返回*os.File。fmt.Fprintf将格式化字符串写入文件,类似Python的f-string或format。defer file.Close()确保文件在函数结束时关闭。
3. 使用 bufio.Writer 进行缓冲写入(类似Python的缓冲I/O)
当需要高效写入大量数据时,可以使用缓冲写入器。
Python示例:
lines = ["Line 1\n", "Line 2\n", "Line 3\n"]
with open("output.txt", "w") as f:
for line in lines:
f.write(line)
Go示例:
package main
import (
"bufio"
"os"
)
func main() {
lines := []string{"Line 1\n", "Line 2\n", "Line 3\n"}
file, err := os.Create("output.txt")
if err != nil {
panic(err)
}
defer file.Close()
writer := bufio.NewWriter(file)
for _, line := range lines {
_, err := writer.WriteString(line)
if err != nil {
panic(err)
}
}
writer.Flush() // 确保所有缓冲数据写入文件
}
bufio.NewWriter创建一个缓冲写入器,减少系统调用次数。writer.Flush()在最后刷新缓冲区,确保所有数据写入文件。
关键点总结:
- 无需手动缓冲区:在Go中,除非处理大量数据,否则直接使用
os.WriteFile或fmt.Fprintf更简单。 - 错误处理:Go要求显式处理错误,使用
if err != nil检查。 - 文件关闭:使用
defer确保文件正确关闭,避免资源泄漏。
这些方法覆盖了从简单到高效的场景,你可以根据需求选择。如果写入内容较小,推荐使用 os.WriteFile;如果需要格式化变量,使用 os.Create 和 fmt.Fprintf;对于大量数据,使用 bufio.Writer。

