go - 返回多个错误或相应地处理它们的惯用方法

标签 go error-handling

我有这段代码,但我不喜欢那种不提 golint 的感觉,不喜欢 error should be the last type when return multiple items (golint) 。解释这段代码:

  • 我想让用户决定他们是否关心返回的任何错误
  • 特别是在这段代码中,有时不需要或不需要音频文件,可以忽略它
  • 无论用户在做什么,都可能总是需要视频和输出文件

我愿意以任何方式重构它(将其分解、移动等)Go 中是否有更惯用的方式来完成这样的事情?

// Download will download the audio and video files to a particular path
func (r *RedditVideo) Download() (outputVideoFileName string, outputAudioFileName string, errVideo error, errAudio error) {
    outputVideoFile, errVideo := downloadTemporaryFile(
        r.VideoURL,
        TemporaryVideoFilePrefix,
    )
    if errVideo == nil {
        outputVideoFileName = outputVideoFile.Name()
    }

    outputAudioFile, errAudio := downloadTemporaryFile(
        r.AudioURL,
        TemporaryAudioFilePrefix,
    )
    if errAudio == nil {
        outputAudioFileName = outputAudioFile.Name()
    }

    return outputVideoFileName, outputAudioFileName, errVideo, errAudio
}

类似地,我发现自己稍后在代码中再次使用了相同的模式:

// SetFiles sets up all of the input files and the output file
func (l *localVideo) SetFiles(inputVideoFilePath string, inputAudioFilePath string, outputVideoFilePath string) (errVideo error, errAudio error, errOutputVideo error) {
	// Set input video file
	l.inputVideoFile, errVideo = os.Open(inputVideoFilePath)
	if errVideo != nil {
		return
	}
	if errVideo = l.inputVideoFile.Close(); errVideo != nil {
		return
	}

	// Set output video file
	l.outputVideoFile, errOutputVideo = os.Create(outputVideoFilePath)
	if errOutputVideo != nil {
		return
	}
	if errOutputVideo = l.outputVideoFile.Close(); errOutputVideo != nil {
		return
	}

	// IMPORTANT! Set input audio file LAST incase it is nil
	l.inputAudioFile, errAudio = os.Open(inputAudioFilePath)
	if errAudio != nil {
		return
	}
	if errAudio = l.inputAudioFile.Close(); errVideo != nil {
		return
	}

	return
}

这次在这段代码中,部分内容与上面相同:

  • 我们关心视频和输出的设置,可能关心也可能不关心音频
  • 有多个错误需要由用户处理

最佳答案

您在标准库中可以看到很多特定函数,它们包装了更通用的非导出函数。请参阅下面的注释代码。

// download is a rather generic function
// and probably you can refactor downloadTemporaryFile
// so that even this function is not needed any more.
func (r *RedditVideo) download(prefix, url string) (filename string, error error) {
    outputFile, err := downloadTemporaryFile(
        r.VideoURL,
        prefix,
    )

    if err == nil {
        return "", fmt.Errorf("Error while download: %s", err)
    }

    return outputFile.Name(), nil
}

// DownloadVideo wraps download, handing over the values specific
// to the video download
func (r *RedditVideo) DownloadVideo() (filename string, averror error) {
    return r.download(TemporaryVideoFilePrefix, r.VideoURL)
}

// DownloadAudio wraps download, handing over the values specific
// to the audio download
func (r *RedditVideo) DownloadAudio() (filename string, averror error) {
    return r.download(TemporaryAudioFilePrefix, r.AudioURL)
}

func main() {

    r := RedditVideo{
        VideoURL: os.Args[1],
        AudioURL: os.Args[2],
    }

    var videoerror, audioerror error
    var videofileName, audiofileName string

    if videofileName, videoerror = r.DownloadVideo(); videoerror != nil {
        fmt.Println("Got an error downloading the video")
    }

    if audiofileName, audioerror = r.DownloadAudio(); audioerror != nil {
        fmt.Println("Got an error downloading the audio")
    }

    fmt.Printf("Video:\t%s\nAudio:\t%s", videofileName, audiofileName)
}

这样一来,返回的错误来自于哪个下载就一目了然了。

关于go - 返回多个错误或相应地处理它们的惯用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53858609/

相关文章:

haskell - 概括没什么

javascript - jQuery/JS随机背景图解决::元素前

带有资源处理程序的spring boot错误页面

reflection - Go Reflect 方法调用无效的内存地址或 nil 指针取消引用

pointers - 请解释 &, 和 * 指针

go - 无法在没有解析错误的情况下在 Google go 中添加时间

go - 当我将外部结构的实例传递给外部结构实现的接口(interface) slice 时,无法访问嵌入式结构

javascript - PostgreSQL未连接到Heroku

ajax - 在Promise对象返回完成后调用的$ .ajax statusCode处理程序

pointers - 为什么 Win32 API 系统调用中使用的缓冲区会转换为 [1<<20]<type> 数组?