我有这样一段代码,例如:
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.MyOtherField
或nil
(当MyField
是nil
时)时,您可以使用它来代替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))
我不确定,但试试这样做。