Golang中如何将*string类型的文件名转换为io.Writer?

Golang中如何将*string类型的文件名转换为io.Writer? 最初,我的代码是这样的:

t := template.Must(template.New("").Parse(someInfileTemplate))
err = t.Execute(os.Stdout, links)

我能够渲染模板并将其打印到 os.Stdout

现在,我扩展了代码,并引入了一个 outFileFlag。这是一个来自 argparse 模块的字符串标志,它返回一个指向字符串的指针。argparse 应该不是问题,因为标准库的 flag 模块也返回指向字符串的指针。

我尝试使用 ioutil.WriteFile,但感到困惑。

如何将一个指向字符串的指针转换为 template.Execute 所接受的 io.Writer


更多关于Golang中如何将*string类型的文件名转换为io.Writer?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

14 回复

你说得对!我现在决定使用一些预定义的文件名。

更多关于Golang中如何将*string类型的文件名转换为io.Writer?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


sntshk:

t.Execute

这个方法的签名是什么?第一个参数的类型是 os.File 吗?

我已更新了问题。

ttemplate.Must(template.New("").Parse(someInfileTemplate))

我不明白。您是如何在那里传递 os.Stdout 的?

这很可能是 text.template.(*Template).Execute() 或其 html 的等效方法。

你不能让它直接接受一个文件名。

你需要使用 os.OpenFile() 来获取一个 *os.File,它实现了 io.Writer

是的,这正是我的意思。用户仍然可以覆盖这个标志。

预定义的是默认文件名。

为什么是预定义的?你仍然可以使用 flags 从用户那里通过命令行参数获取它。但在那种情况下使用 os.Stdout 是没有意义的。

尤其不能作为一个文件名……

这就是我感到困惑的原因。

os.Open 用于读取文件,正如我所说,你需要使用 os.OpenFile()

也许你应该实际 fmt.Print() 一下 err 变量。这样你才能了解哪里出错了。

f, err := os.OpenFile(*outFileFlag, os.O_CREATE, 644)
if err != nil {
	panic(err)
}

这段代码在其他文件上可以正常工作,但在 os.Stdout 上会失败:

panic: open os.Stdout: permission denied

	f, err := os.Open(*outFileFlag)
	if err != nil {
		exit("Error opening the out file.")
	}

	t := template.Must(template.New("").Parse(someInfileTemplate))
	err = t.Execute(f, links)
	if err != nil {
		exit("Cannot execute the template")
	}

程序在第一个 exit() 处退出。

无需打开标准输出。它已经定义在 os.go 中,可以直接使用:

var (
    Stdin  = NewFile(uintptr(syscall.Stdin), "/dev/stdin")
    Stdout = NewFile(uintptr(syscall.Stdout), "/dev/stdout")
    Stderr = NewFile(uintptr(syscall.Stderr), "/dev/stderr")
)

好的,我现在明白了。

你是否考虑过遵循一些Linux惯例,使用 - 作为默认文件名,即代表 os.Stdout

func writerFromFlag(flag *string) (io.Writer, error) {
  if *flag == "-" {
    return os.Stdout, err
  }
  return os.OpenFile(*flag, os.O_CREATE, 644)
}

要将 *string 类型的文件名转换为 io.Writer,你需要先打开文件,然后使用返回的文件句柄作为 io.Writer。以下是具体实现:

package main

import (
    "os"
    "text/template"
)

func main() {
    // 假设 outFileFlag 是 *string 类型
    var outFileFlag *string
    // 示例:outFileFlag 指向文件名
    filename := "output.txt"
    outFileFlag = &filename

    // 解析模板
    t := template.Must(template.New("").Parse("Hello, {{.}}!"))

    // 处理输出文件
    var writer io.Writer = os.Stdout // 默认输出到标准输出
    if outFileFlag != nil && *outFileFlag != "" {
        file, err := os.Create(*outFileFlag)
        if err != nil {
            panic(err)
        }
        defer file.Close()
        writer = file
    }

    // 执行模板
    err := t.Execute(writer, "World")
    if err != nil {
        panic(err)
    }
}

如果需要直接使用 ioutil.WriteFile,可以这样处理:

import "io/ioutil"

// 先渲染到缓冲区
var buf bytes.Buffer
err := t.Execute(&buf, links)
if err != nil {
    panic(err)
}

// 写入文件
if outFileFlag != nil && *outFileFlag != "" {
    err = ioutil.WriteFile(*outFileFlag, buf.Bytes(), 0644)
    if err != nil {
        panic(err)
    }
}

关键点:

  1. 通过 os.Create() 创建文件并获取 io.Writer
  2. 始终检查指针是否为 nil 和字符串是否为空
  3. 使用 defer 确保文件正确关闭
回到顶部