Home > other >  Is there any way to handle nil pointer in Golang without using if/else?
Is there any way to handle nil pointer in Golang without using if/else?

Time:12-15

I have this piece of code for example:

type MyStruct struct {    
    ...
    MyField *MyOtherStruct
    ...
}

type MyOtherStruct struct {
    ...
    MyOtherField *string
    ...
}

// I have a fuction that receive MyOtherField as parameter
func MyFunc(myOtherField *string) {
    ...
}

// How can I avoid using if/else here
if MyStruct.MyField != nil {
    MyFunc((*MyStruct.MyField).MyOtherField)
} else {
    MyFunc(nil)
}

In my example, I have to use if else to handle whether MyStruct.MyField is nil or not. I would like to find a way to shorten my code.

I would like to find some way like MyFunc(MyStruct.MyField ? (*MyStruct.MyField).MyOtherField : nil) in JavaScript.

CodePudding user response:

No, you cannot do what you used to do in JS. It is just syntactic sugar. But, there are some alternatives.

First, you can simply write:

if MyStruct.MyField != nil {
    MyFunc(MyStruct.MyField.MyOtherField)
} else {
    MyFunc(nil)
}

In some cases it may make sense to write getters that work with pointer receivers:

func (m *MyOtherStruct) GetOtherField() *OtherFieldType {
   if m==nil {
      return nil
   }
   return m.OtherField
}

Then you can do:

MyFunc(MyStruct.MyField.GetOtherField())

This is how gRPC generates Go models. It is not usually advisable, though. It hides subtle bugs. It is best to be explicit and check where you use it.

CodePudding user response:

GoLang has no 'coalescing nil' operator or ternary conditions (by design, currently at least) but if you want to remove the else from your main flow you can extract it into a helper func.

I've illustrated this as a func with a *MyStruct receiver but it could equally exist as a standalone fun accepting a *MyStruct arg:

func (ms *MyStruct) getMyOtherFieldOrNil() *string {
   if ms.MyField == nil {
      return nil
   }
   return ms.MyField.MyOtherField
}

The name of the func makes it clear that a nil result is legitimate, to avoid any potential for confusion.

Then, when you need the MyField.MyOtherField or nil (when MyField is nil) you can use this in place of the if {} else {} construct:

    ms := &MyStruct{}

    // ...

    MyFunc(ms.getMyOtherFieldOrNil())

Footnote

This is similar to Burak's answer but avoids the potential pitfalls of nil receivers which I believe are responsible for the "subtle bugs" mentioned. This slightly higher level helper func will simply panic if called on a nil *MyStruct receiver (as it should), but otherwise achieves much the same purpose.

CodePudding user response:

You cannot avoid using if else. Even through you define a getter for MyStruct, there still if else inside. So I suggest that you should keep your original code for clear.

CodePudding user response:

func TernaryFunc(statement bool, a, b interface{}) interface{} {
    if statement {
        return a
    }
    return b
}

MyFunc(TernaryFunc(MyStruct.MyField == nil, (*MyStruct.MyField).MyOtherField, nil).(string))

I'm not sure but try some things like this.

  •  Tags:  
  • go
  • Related