Michael A
Michael A

Reputation: 9900

Check if every item in a struct is unchanged

I have the following package:

// Contains state read in from the command line
type State struct {
    Domain          string  // Domain to check for
    DomainList      string  // File location for a list of domains
    OutputNormal    string  // File to output in normal format
    OutputDomains   string  // File to output domains only to
    Verbose         bool    // Verbose prints, incl. Debug information
    Threads         int     // Number of threads to use
    NoColour        bool    // Strip colour from output
    Silent          bool    // Output domains only
    Usage           bool    // Print usage information
}

func InitState() (state State) {
    return State { "", "", "", "", false, 20, false, false, false }
}

func ValidateState(s *State) (result bool, error string ) {
    if s.Domain == "" && s.DomainList == "" {
        return false, "You must specify either a domain or list of domains to test"
    }

    return true, ""
}

Within ValidateState() I would like to return true if every item in State is the same as what is defined in InitState(). I can see a few ways to do this, but nothing that seems concise. I would greatly value some direction!

Upvotes: 1

Views: 165

Answers (1)

icza
icza

Reputation: 417592

Struct values are comparable if all their fields are comparable (see Spec: Comparison operators). And since in your case this holds, we can take advantage of this.

In your case the simplest and most efficient way to achieve this is to save a struct value holding the initial value, and whenever you want to tell if a struct value (if any of its fields) has changed, simply compare it to the saved, initial value. This is all it takes:

var defaultState = InitState()

func isUnchanged(s State) bool {
    return s == defaultState
}

Testing it:

s := InitState()
fmt.Println(isUnchanged(s))

s.Threads = 1
fmt.Println(isUnchanged(s))

Output (try it on the Go Playground):

true
false

Note that this solution will still work without any modification if you change the State type by adding / removing / renaming / rearranging fields as long as they all will still be comparable. As a counter example, if you add a field of slice type, it won't work anymore as slices are not comparable. It will result in a compile-time error. To handle such cases, reflect.DeepEqual() might be used instead of the simple == comparison operator.

Also note that you should create default values of State like this:

func NewState() State {
    return State{Threads: 20}
}

You don't have to list fields whose values are the zero values of their types.

Upvotes: 2

Related Questions