英文:
Invalid memory address or nil pointer dereference on slice
问题
为什么在运行时 greets 给我返回 invalid memory address or nil pointer dereference
错误?
type Response struct {
Message string `json:"message"`
}
type ResponseList struct {
Items []*Response `json:"items"`
}
func (gs *GreetingService) List(r *http.Request, req *Request, resp *ResponseList) error {
greets := make([]*Response, 2, 2)
greets[0].Message = "hello"
greets[1].Message = "goodbye"
resp.Items = greets
return nil
}
在这段代码中,greets
是一个指向 Response
结构体的切片。在创建 greets
切片时,你指定了它的长度和容量都为 2。然而,在给 greets
中的元素赋值时,你没有为每个元素分配内存空间,导致出现了空指针解引用的错误。
要解决这个问题,你需要为 greets
中的每个元素分配内存空间。可以通过使用 new
关键字或者直接创建 Response
结构体的实例来完成。以下是修复后的代码示例:
func (gs *GreetingService) List(r *http.Request, req *Request, resp *ResponseList) error {
greets := make([]*Response, 2, 2)
greets[0] = &Response{Message: "hello"}
greets[1] = &Response{Message: "goodbye"}
resp.Items = greets
return nil
}
修复后的代码会为 greets
中的每个元素分配内存空间,并将相应的消息赋值给它们。这样就可以避免空指针解引用错误的发生。
英文:
Why does greets give me invalid memory address or nil pointer dereference
when running?
type Response struct {
Message string `json:"message"`
}
type ResponseList struct {
Items []*Response `json:"items"`
}
func (gs *GreetingService) List(r *http.Request, req *Request, resp *ResponseList) error {
greets := make([]*Response,2,2)
greets[0].Message="hello"
greets[1].Message="goodbye"
resp.Items = greets
return nil
}
答案1
得分: 8
你没有分配 Response 对象,只是分配了指针。指针被初始化为 nil。
你可以这样说 greets[0] := &Response{Message: "hello"}
。或者,更好的方式是,从一个空切片开始,然后使用 append
添加任意数量的 *Response
:
greets := []*Response{} // 或者 ResponseList{}
greets = append(greets, &Response{Message: "hello"})
greets = append(greets, &Response{Message: "goodbye"})
编辑: 注意 Anonymous 的替代方法:如果你知道 Response
的数量,你可以使用字面量来设置整个结构,例如 resp.Items = {{Message: "hello"}}
。即使 Response
是一个指针,也可以工作,并且不需要在每个 Response
上显式指定类型名称。非常酷。
英文:
You haven't allocated the Response objects, just pointers. Pointers are inited to nil.
You could say greets[0] := &Response{Message: "hello"}
. Or, perhaps better, start with an empty slice and append
as many *Response
s as you want:
greets := []*Response{} // or ResponseList{}
greets = append(greets, &Response{Message: "hello"})
greets = append(greets, &Response{Message: "goodbye"})
Edit: Note Anonymous's alternative: you can use a literal to set up the whole structure if you know the number of Response
s, as in resp.Items = {{Message: "hello"}}
. Works even though Response is a pointer, and works without an explicit type name on each Response
. Very cool.
答案2
得分: 2
在Go语言中,对切片和结构体字面量的支持可以帮助你避免样板代码,并确保你的代码正确无误。
以下是使用切片字面量编写List
方法的示例代码:
func (gs *GreetingService) List(r *http.Request, req *Request, resp *ResponseList) error {
resp.Items = []*Response{
{Message: "hello"},
{Message: "goodbye"},
}
return nil
}
这段代码使用切片字面量为resp.Items
赋值,其中包含了两个Response
结构体字面量。
英文:
The support for slice and struct literals in Go can help you avoid the boilerplate as well as get your code right.
Here's how to write your List
method using a slice literal.
func (gs *GreetingService) List(r *http.Request, req *Request, resp *ResponseList) error {
resp.Items = []*Response{
{Message: "hello"},
{Message: "goodbye"},
}
return nil
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论