如何修复Go语言中的空指针解引用错误?

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

How to fix nil pointer dereference in Go?

问题

我简化了我的案例如下:

type Service struct {
	value *string
}

func (service Service) Init() {
	if service.value != nil {
		return
	}

	value := "some value"
	service.value = &value
}

func TestPointer(t *testing.T) {
	service := Service{}
	service.Init()
	require.NotNil(t, service.value)
}

当我进行断言时,这个测试失败了,因为service.value是空的。我无法理解为什么会这样,因为我调用了Init方法来赋值。显然,在Init方法结束时,值就丢失了。但是我该如何修复它呢?

在Go Playground上的链接:https://goplay.tools/snippet/qxIFRjSZxLl

英文:

I simplified my case to this:

type Service struct {
	value *string
}

func (service Service) Init() {
	if service.value != nil {
		return
	}

	value := "some value"
	service.value = &value
}

func TestPointer(t *testing.T) {
	service := Service{}
	service.Init()
	require.NotNil(t, service.value)
}

This test is failing because service.value is nil when I'm making the assert. I can't understand why though since I'm calling the Init method which assigns it. Well it's clear that the value gets lost at the end of the Init method. But how can I fix it?

Here it is on Go Playgroung: https://goplay.tools/snippet/qxIFRjSZxLl

答案1

得分: 1

包含中文翻译的代码如下:

package main

import (
	"fmt"
)

type Service struct {
	value *string
}

func (service *Service) Init() {
	if service.value != nil {
		return
	}

	value := "some value"
	service.value = &value
}

func main() {
	service := Service{}
	service.Init()
	fmt.Println(*service.value)
}

我修改了你的goplayground文件。你缺少了指针func (service *Service) Init()。使用非指针接收器调用Init()不会修改原始的Service对象,而使用指针接收器调用Init()会修改原始的Service对象。


第一个版本func (service Service) Init()使用非指针接收器,这意味着将Service对象的副本传递给函数。这个副本是Service结构的一个新实例,独立于原始的Service对象。如果在函数内部修改副本,这些更改不会反映在原始的Service对象中。

第二个版本func (service *Service) Init()使用指针接收器,这意味着函数使用指向原始Service对象的指针进行调用。如果在函数内部修改对象,这些更改将反映在原始的Service对象中。

英文:
package main

import (
	"fmt"
)

type Service struct {
	value *string
}

func (service *Service) Init() {
	if service.value != nil {
		return
	}

	value := "some value"
	service.value = &value
}

func main() {
	service := Service{}
	service.Init()
	fmt.Println(*service.value)
}

I have modified your goplayground file. You are missing the pointer func (service *Service) Init(). calling Init() with a non-pointer receiver does not modify the original Service object, while calling Init() with a pointer receiver modifies the original Service object.


The first version func (service Service) Init() uses a non-pointer receiver, which means that a copy of the Service object is passed to the function. This copy is a new instance of the Service struct that is independent of the original Service object. If you modify the copy inside the function, the changes will not be reflected in the original Service object.

The second version func (service *Service) Init() uses a pointer receiver, which means that the function is called with a pointer to the original Service object. If you modify the object inside the function, the changes will be reflected in the original Service object.

huangapple
  • 本文由 发表于 2023年6月27日 20:12:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/76564736.html
匿名

发表评论

匿名网友

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

确定