英文:
Is there any way to handle nil pointer in Golang without using if/else?
问题
我有一个示例代码:
type MyStruct struct {
...
MyField *MyOtherStruct
...
}
type MyOtherStruct struct {
...
MyOtherField *string
...
}
// 我有一个接收 MyOtherField 作为参数的函数
func MyFunc(myOtherField *string) {
...
}
// 如何避免在这里使用 if/else
if MyStruct.MyField != nil {
MyFunc((*MyStruct.MyField).MyOtherField)
} else {
MyFunc(nil)
}
在我的示例中,我必须使用 if/else 来处理 MyStruct.MyField
是否为 nil。我想找到一种缩短代码的方法。
我想找到一种类似于 JavaScript 中的 MyFunc(MyStruct.MyField ? (*MyStruct.MyField).MyOtherField : nil)
的方式。
英文:
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.
答案1
得分: 5
不,你不能像在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模型的方式。尽管如此,通常不建议这样做,因为它会隐藏一些微妙的错误。最好是明确地检查你在使用它的地方。
英文:
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.
答案2
得分: 3
GoLang没有'coalescing nil'运算符或三元条件(至少目前如此),但如果你想从主流程中删除else
,你可以将其提取到一个辅助函数中。
我将其示例化为一个带有*MyStruct
接收器的函数,但它也可以作为一个独立的函数接受*MyStruct
参数存在:
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的答案类似,但避免了我认为与"subtle bugs"有关的nil receivers
的潜在问题。这个稍微高级的辅助函数只会在一个nil
的*MyStruct接收器上调用时引发panic(正如它应该做的),但在其他情况下实现了相同的目的。
英文:
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.
答案3
得分: 1
你无法避免使用 if else。即使你为 MyStruct 定义了一个 getter,其中仍然包含 if else。所以我建议你保留原始代码以保持清晰。
英文:
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.
答案4
得分: -1
func TernaryFunc(statement bool, a, b interface{}) interface{} {
if statement {
return a
}
return b
}
MyFunc(TernaryFunc(MyStruct.MyField == nil, (*MyStruct.MyField).MyOtherField, nil).(string))
我不确定,但可以尝试像这样的一些方法。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论