运行时错误:访问结构中的 Reader 时出错。

huangapple go评论75阅读模式
英文:

Runtime error: When accessing a Reader in struct

问题

我是你的中文翻译助手,以下是你要翻译的内容:

我刚开始学习Go语言,尝试实现一个用于视频操作(下载、上传、转码)的接口。在我的下载方法中,我创建了一个Reader并将其赋值给结构体变量'fileContent'。然后我想在我的上传方法中访问这个Reader,但是它抛出了一个运行时错误。

panic: runtime error: invalid memory address or nil pointer dereference

以下是我在Go Playground中的代码链接。任何帮助都将非常感谢。

https://play.golang.org/p/ib38IQ6AZI

英文:

I'm new to go and trying to implement an interface for video operations (download, upload, transcode). In my download method I'm creating a Reader and assigning it to struct variable 'fileContent'. I'd then like to access the Reader in my upload method but it's throwing a runtime error.

> panic: runtime error: invalid memory address or nil pointer dereference

Below is a link to my code in go playground. Any help would be great.

https://play.golang.org/p/ib38IQ6AZI

答案1

得分: 3

问题在于你使用了非指针接收器:

func (b BaseVideo) Download() (err error) {
    b.fileContent = bytes.NewReader([]byte("abc"))
    return nil
}

这意味着你调用 Download() 方法时,它会得到一个 BaseVideo 值的副本。你在方法内修改了这个副本(将一个新的 Reader 赋值给 fileContent 字段),但原始的 BaseVideo 不会被修改

解决方法是使用指针接收器:

func (b *BaseVideo) Download() (err error) {
    b.fileContent = bytes.NewReader([]byte("abc"))
    return nil
}

当然,如果你将接收器修改为指针,类型 BaseVideo 将不再实现 Video 接口,只有指向 BaseVideo 的指针才会实现该接口,因此还需要修改 NewBaseVideo,使其返回指向结构体值的指针:*BaseVideo。你可以通过取结构体字面量的地址来实现这一点:

func NewBaseVideo(path, name string) Video {
    return &BaseVideo{
        Path: path,
        Name: name,
    }
}
英文:

The problem is that you're using non-pointer receiver:

func (b BaseVideo) Download() (err error) {
	b.fileContent = bytes.NewReader([]byte("abc"))
	return nil
}

This means your Download() method gets a copy of the BaseVideo value you're calling it on. You modify this copy inside the method (you assign a new Reader to the fileContent field), but the original BaseVideo will not be modified.

Solution: use a pointer receiver:

func (b *BaseVideo) Download() (err error) {
	b.fileContent = bytes.NewReader([]byte("abc"))
	return nil
}

Of course if you modify the receiver to be a pointer, the type BaseVideo will no longer implement the Video interface, only a pointer to BaseVideo, so also modify NewBaseVideo to return a pointer to the struct value: *BaseVideo. You can achieve this by taking the address of the struct literal:

func NewBaseVideo(path, name string) Video {
	return &BaseVideo{
		Path: path,
		Name: name,
	}
}

答案2

得分: 2

如果你想在方法中改变值,方法的接收者应该是一个指针。将

func (b BaseVideo) Download() (err error)

替换为

func (b *BaseVideo) Download() (err error)

在playground上的可工作代码:https://play.golang.org/p/hZ8-RwzVYh。

英文:

If you want to mutate the value in a methods, the receiver of the method should be a pointer. Replace

func (b BaseVideo) Download() (err error)

and such with

func (b *BaseVideo) Download() (err error)

Working code on the playground: https://play.golang.org/p/hZ8-RwzVYh.

huangapple
  • 本文由 发表于 2015年11月11日 19:24:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/33649512.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定