简洁的 nil 检查结构字段指针?
Concise nil checks for struct field pointers?
假设我有这个结构:
type Foo struct {
Bar *string `json:"bar"`
Baz *int64 `json:"baz,omitempty"`
Qux *string `json:"qux"`
Quux string `json:"quux"`
}
解组 json 后,我像这样检查 nil:
switch {
case f.Bar == nil:
return errors.New("Missing 'bar'")
case f.Baz == nil:
f.Baz = 42
case f.Qux == nil:
return errors.New("Missing 'qux'")
}
(或通过一系列 if
语句等...)
我知道我可以将所有 nil
比较放在一个逗号分隔 case
中,但是每个 nil
检查都会有不同的 returns.
我的问题:是否有更简单的 nil 检查方法?
问你一个问题:你想减少多少冗长?因为你想在不同的条件下做不同的事情(不同的领域是nil
)。您的代码包含这些不同的东西和不同的条件。除此之外,代码中的 "redundant" 只是 switch
和 case
关键字。你想把他们排除在外吗?因为其余的不是"redundant",他们是必需的。
另请注意,在 Go 中,即使没有 break
(与其他语言不同),case
也不会失败,因此在上面的示例中,如果 f.Baz
是 nil
,你将它设置为42
并且f.Qux
不会被检查(所以不会返回error
),但是如果f.Baz
是非nil
并且 f.Qux
是 nil
,将返回 error
。我知道这只是一个例子,但要记住这一点。如果您使用 switch
,您应该首先处理 error
!或者使用 if
语句,然后无论字段检查的顺序如何,都会检测并返回错误。
您使用 switch
编写的代码简洁高效。如果你想让它不那么冗长,可读性(和性能)就会受到影响。
您可以使用辅助函数来检查指针值是否为 nil
:
func n(i interface{}) bool {
v := reflect.ValueOf(i)
return v.Kind() == reflect.Ptr && v.IsNil()
}
并使用它:
func check(f *Foo) error {
switch {
case n(f.Bar):
return errors.New("Missing 'bar'")
case n(f.Qux):
return errors.New("Missing 'qux'")
case n(f.Baz):
x := int64(42)
f.Baz = &x
}
return nil
}
或使用 if
语句:
func check2(f *Foo) error {
if n(f.Bar) {
return errors.New("Missing 'bar'")
}
if n(f.Qux) {
return errors.New("Missing 'qux'")
}
if n(f.Baz) {
x := int64(42)
f.Baz = &x
}
return nil
}
在 Go Playground 上试试这些。
假设我有这个结构:
type Foo struct {
Bar *string `json:"bar"`
Baz *int64 `json:"baz,omitempty"`
Qux *string `json:"qux"`
Quux string `json:"quux"`
}
解组 json 后,我像这样检查 nil:
switch {
case f.Bar == nil:
return errors.New("Missing 'bar'")
case f.Baz == nil:
f.Baz = 42
case f.Qux == nil:
return errors.New("Missing 'qux'")
}
(或通过一系列 if
语句等...)
我知道我可以将所有 nil
比较放在一个逗号分隔 case
中,但是每个 nil
检查都会有不同的 returns.
我的问题:是否有更简单的 nil 检查方法?
问你一个问题:你想减少多少冗长?因为你想在不同的条件下做不同的事情(不同的领域是nil
)。您的代码包含这些不同的东西和不同的条件。除此之外,代码中的 "redundant" 只是 switch
和 case
关键字。你想把他们排除在外吗?因为其余的不是"redundant",他们是必需的。
另请注意,在 Go 中,即使没有 break
(与其他语言不同),case
也不会失败,因此在上面的示例中,如果 f.Baz
是 nil
,你将它设置为42
并且f.Qux
不会被检查(所以不会返回error
),但是如果f.Baz
是非nil
并且 f.Qux
是 nil
,将返回 error
。我知道这只是一个例子,但要记住这一点。如果您使用 switch
,您应该首先处理 error
!或者使用 if
语句,然后无论字段检查的顺序如何,都会检测并返回错误。
您使用 switch
编写的代码简洁高效。如果你想让它不那么冗长,可读性(和性能)就会受到影响。
您可以使用辅助函数来检查指针值是否为 nil
:
func n(i interface{}) bool {
v := reflect.ValueOf(i)
return v.Kind() == reflect.Ptr && v.IsNil()
}
并使用它:
func check(f *Foo) error {
switch {
case n(f.Bar):
return errors.New("Missing 'bar'")
case n(f.Qux):
return errors.New("Missing 'qux'")
case n(f.Baz):
x := int64(42)
f.Baz = &x
}
return nil
}
或使用 if
语句:
func check2(f *Foo) error {
if n(f.Bar) {
return errors.New("Missing 'bar'")
}
if n(f.Qux) {
return errors.New("Missing 'qux'")
}
if n(f.Baz) {
x := int64(42)
f.Baz = &x
}
return nil
}
在 Go Playground 上试试这些。