douye4254
2018-03-24 15:32 阅读 60
已采纳

如何检查* struct的所有字段是否均为nil?

I'm not quite sure how to address this question, please feel free to edit.

With the first code block below, I am able to check if a all fields of a struct are nil.

In reality however, the values injected in the struct, are received as args.Review (see second code block below).

In the second code block, how can I check if all fields from args.Review are nil?

Try it on Golang Playground

package main

import (
    "fmt"
    "reflect"
)

type review struct {
    Stars      *int32  `json:"stars" bson:"stars,omitempty" `
    Commentary *string `json:"commentary" bson:"commentary,omitempty"`
}

func main() {

    newReview := &review{
        Stars: nil,
        // Stars:   func(i int32) *int32 { return &i }(5),

        Commentary: nil,
        // Commentary: func(i string) *string { return &i }("Great"),
    }

    if reflect.DeepEqual(review{}, *newReview) {
        fmt.Println("Nothing")
    } else {
        fmt.Println("Hello")
    }

}

Try the second code on Golang Playground This code below gets two errors:

prog.go:32:14: type args is not an expression

prog.go:44:27: args.Review is not a type

package main

import (
    "fmt"
    "reflect"
)

type review struct {
    Stars      *int32  `json:"stars" bson:"stars,omitempty" `
    Commentary *string `json:"commentary" bson:"commentary,omitempty"`
}

type reviewInput struct {
    Stars      *int32
    Commentary *string
}

type args struct {
    PostSlug string
    Review   *reviewInput
}

func main() {
    f := &args {
        PostSlug: "second-post",
        Review: &reviewInput{
            Stars:  func(i int32) *int32 { return &i }(5),
            Commentary: func(i string) *string { return &i }("Great"),
        },

    }
    createReview(args)
}

func createReview(args *struct {
    PostSlug string
    Review   *reviewInput
}) {
    g := &review{
        Stars: args.Review.Stars,
        Commentary: args.Review.Commentary,
    }

    if reflect.DeepEqual(args.Review{}, nil) {
        fmt.Println("Nothing")
    } else {
        fmt.Println("Something")
    }
}
  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

1条回答 默认 最新

  • 已采纳
    dsf6565 dsf6565 2018-03-24 20:12

    If you're dealing with a small number of fields you should use simple if statements to determine whether they are nil or not.

    if args.Stars == nil && args.Commentary == nil {
        // ...
    }
    

    If you're dealing with more fields than you would like to manually spell out in if statements you could use a simple helper function that takes a variadic number of interface{} arguments.

    func AllNil(vv ...interface{}) bool {
        for _, v := range vv {
            if v != nil {
                return false
            }
        }
        return true
    }
    
    if AllNil(args.Stars, args.Commentary, args.Foo, args.Bar, args.Baz) {
        // ...
    }
    

    Or you can use the reflect package to do your bidding.

    func NilFields(x interface{}) bool {
        rv := reflect.ValueOf(args)
        rv = rv.Elem()
    
        for i := 0; i < rv.NumField(); i++ {
            if !rv.Field(i).IsNil() {
                return false
            }
        }
        return true
    }
    
    if NilFields(args) {
       // ...
    }
    

    But keep in mind that there is this: Check for nil and nil interface in Go

    点赞 评论 复制链接分享

相关推荐