What's purpose of initializing a struct as a pointer?

114 views Asked by At

Zap initializes its default option struct as follows in its grpc interceptor:

var (
    defaultOptions = &options{
        levelFunc:       DefaultCodeToLevel,
        shouldLog:       grpc_logging.DefaultDeciderMethod,
        codeFunc:        grpc_logging.DefaultErrorToCode,
        durationFunc:    DefaultDurationToField,
        messageFunc:     DefaultMessageProducer,
        timestampFormat: time.RFC3339,
    }
)

And the later zap performs a copy of values:

*optCopy = *defaultOptions

What is the purpose of declaring the variable defaultOptions as a pointer and then later dereferencing it for copying? I was wondering if there is any issue with not using pointer:

   defaultOptions = options{
        levelFunc:       DefaultCodeToLevel,
        shouldLog:       grpc_logging.DefaultDeciderMethod,
        codeFunc:        grpc_logging.DefaultErrorToCode,
        durationFunc:    DefaultDurationToField,
        messageFunc:     DefaultMessageProducer,
        timestampFormat: time.RFC3339,
    }

    optCopy = &options{}
    *optCopy = defaultOptions
   
2

There are 2 answers

2
Fernando Barbosa Gomes On

My guess, based on previous issues I had with big systems, is that with configuration structs, if for any reason some part of your software changes the value of something, that change will propagate to any function/member who has that pointer, and most of the times you don't want that to happen, you usually want that the configuration that you probably read from a file, stays the same, even if some function needs to do a transformation of a specific field of the struct holding that configuration.

So basically, you keep the original struct fresh, but you can send the pointer around to have its contents copied anywhere. That's my educated guess, it is most likely an application architecture decision.

Edit: After further pondering: If the author of the code had in his mind the idea of moving that data structure everywhere in his code, in multiple levels deep and broad, declaring it as value would mean he would have to copy it every time he wanted to move the data from function to function, or that the data structure could be erased by the end of execution of scope, whereas with a pointer he can move only the pointer around (much faster) and then only copy the data once the pointer arrives at the destination function.

2
Dino Dini On

A possible advantage with using a pointer is that you can then have that pointer set to nil; obviously if it is nil, you can't dereference it; but this might be used to indicate that there are no options and there may be code to handle this.

Caveat: I am not a Go programmer.