是否有任何方法来处理nil指针在Golang不使用if/else?



我有这样一段代码,例如:

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)
}

在我的例子中,我必须使用if else来处理MyStruct.MyField是否为nil。我想找到一种方法来缩短我的代码。

我想在JavaScript中找到一些像MyFunc(MyStruct.MyField ? (*MyStruct.MyField).MyOtherField : nil)的方法。

不,你不能做你以前在JS中做的事情。它只是语法上的糖。但是,有一些替代方案。

首先,你可以简单地写:

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

在某些情况下,编写与指针接收器一起工作的getter可能是有意义的:

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

那么你可以这样做:

MyFunc(MyStruct.MyField.GetOtherField())

这就是gRPC生成Go模型的方式。不过,这通常是不可取的。它隐藏了细微的bug。最好是明确的,并检查在哪里使用它。

GoLang没有'coalescing nil'操作符或三元条件(根据设计,至少目前),但如果您想从主流程中删除else,您可以将其提取到辅助函数中。

我已经说明了这是一个具有*MyStruct接收器的函数,但它同样可以作为一个接受*MyStruct参数的独立fun存在:

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

函数的名称清楚地表明nil结果是合法的,以避免任何潜在的混淆。

然后,当您需要MyField.MyOtherFieldnil(当MyFieldnil时)时,您可以使用它来代替if {} else {}结构:

ms := &MyStruct{}
// ...
MyFunc(ms.getMyOtherFieldOrNil())

脚注

这与Burak的答案相似,但避免了nil receivers的潜在陷阱,我认为这些陷阱是导致"微妙错误"的原因。提及。如果在nil*MyStruct接收器上调用这个稍微高级一点的helper函数,它只会出现panic(它应该这样做),但在其他方面实现了大致相同的目的。

你不能避免使用if else。即使你为MyStruct定义了getter,里面仍然有if else。因此,我建议您保留原始代码以保持清晰。

func TernaryFunc(statement bool, a, b interface{}) interface{} {
if statement {
return a
}
return b
}
MyFunc(TernaryFunc(MyStruct.MyField == nil, (*MyStruct.MyField).MyOtherField, nil).(string))

我不确定,但试试这样做。

最新更新