在结构体属性中捕获空指针解引用错误。

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

Catch nil pointer dereference in Struct properties

问题

我正在尝试找到在访问结构体属性时捕获"空指针解引用"的最佳方法。

假设我们有以下结构体(代码仅用于演示,我的意图是传达一个观点):

type Location struct {
  coordinates *Coordinates
}

type Coordinates struct {
  lat *Latitude
  lon *Longitude
}

type Latitude struct {
  lat float64
}

type Longitude struct {
  lon float64
}

初始化空的Location并访问loc.coordinates.lat显然会产生预期的错误:

loc := Location{}
fmt.Println(loc.coordinates.lat) // 运行时错误:无效的内存地址或空指针解引用

为了解决这个问题,我可以这样做:

if loc.coordinates != nil {
  fmt.Println(loc.coordinates.lat)
}

但是,在这种情况下,如果我想打印Latitudelat属性,我必须添加另一个if语句,如下所示:

if loc.coordinates != nil {
  if loc.coordinates.lat != nil {
    fmt.Println(loc.coordinates.lat.lat)
  }
}

我想知道是否有其他处理这种情况的方法,而不必检查每个地址是否等于nil。在Go语言中是否有类似于val, ok := someMap["foo"]的用于结构体的方法?

英文:

I am trying to find the best way to catch nil pointer dereference when trying to access the property of the struct that is an address to another type.

Assume we have these structs (The code is for demo only. My intention is to convey a point)

type Location struct {
  coordinates *Coordinates
}

type Coordinates struct {
  lat *Latitude
  lon *Longitude
}

type Latitude struct {
  lat float64
}

type Longitude struct {
  lon float64
}

Initialising empty Location and accessing loc.coordinates.lat obviously yields an error as expected

loc := Location{}
fmt.Println(loc.coordinates.lat) // runtime error: invalid memory address or nil pointer dereference

To solve this problem I can do

if loc.coordinates != nil {
  fmt.Println(loc.coordinates.lat)
}

But in this case, if I want to print out lat property of Latitude I must add another if statement as follows

 if loc.coordinates != nil {
    if(loc.coordinates.lat != nil){
          fmt.Println(loc.coordinates.lat.lat)
    }
  }

I am wondering if there is any other way of handling this situation without checking if every address is not equal to nil. Is there anything like val, ok := someMap["foo"] in Go for structs?

答案1

得分: 2

如果你定义了指针类型,你必须处理它们可能为nil的情况。一种方法是检查每次访问。另一种方法是使用可以处理nil接收者的getter方法:

func (c *Coordinates) GetLat() (Latitude, bool) {
  if c == nil {
    return Latitude{}, false
  }
  return c.lat, true
}

func (l *Location) GetCoordinates() *Coordinates {
   if l == nil {
      return nil
   }
   return l.coordinates
}

lat, ok := l.GetCoordinates().GetLat()
if ok {
   // 存在有效的纬度
}

希望对你有帮助!

英文:

If you define pointer types, you have to deal with them being possibly nil. One way to do it is to check every access. Another way is using getters that can deal with nil receivers:

func (c *Coordinates) GetLat() (Latitude,bool) {
  if c==nil {
    return Latitude{}, false
  }
  return c.lat,true
}

func (l *Location) GetCoordinates() *Coordinates {
   if l==nil {
      return nil
   }
   return l.coordinates
}

lat, ok:=l.GetCoordinates().GetLat()
if ok {
   // there is a valid lat
}

答案2

得分: 2

我在想是否有其他处理这种情况的方法,而不是检查每个地址是否不等于nil。

没有,没有其他方法。(从生成的panic中恢复是一种不好的做法,容易出错且速度慢。)

在Go语言中,是否有类似于val, ok := someMap["foo"]这样的用于结构体的方式?

没有。

英文:

> I am w[o]ndering if there is any other way of handling this situation without checking if every address is not equal to nil.

No, there isn't. (Recovering from the generated panic is a bad practice, error prone and slow.)

> Is there anything like val, ok := someMap["foo"] in Go for structs?

No.

huangapple
  • 本文由 发表于 2021年11月23日 12:12:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/70075324.html
匿名

发表评论

匿名网友

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

确定