Michael
Michael

Reputation: 153

Go pointer swap issue

I'm trying to swap the pointer for a struct in Go, running in a function that is attached to it:

func ( config *Config ) ReLoadConfigFile( configPath string ) error {
if ( len( configPath ) > 0 ) {
    newConfig := Config{};
    err := newConfig.LoadFromFile( configPath );

    //Swap the configs, ensuring to lock the config for the swap
    if ( err == nil ) {
        config.Lock.Lock( );
        defer config.Lock.Unlock( );
        config = &newConfig;
    } else {
        errorString := "Unable To Reload Config At Path: " + configPath;
        return fmt.Errorf( errorString );
    }
} else {
    return fmt.Errorf( "No Config Given To Reload" );
}
return nil;

}

I've added a couple of prints in, both inside this function for config and newConfig as well as the same pointer outside the function, however it does not appear that the pointer swap is working correctly, as config and the print outside the function still print the previous version, rather than newConfig that it is my understanding I am changing the pointer too.

I'm pretty new to Go, just to check I'm not going mad I've recreated the same thing in Cpp and it works:

int *Temp1 = NULL;
int Temp2 = 123456;

Temp1 = &Temp2;

Where it will make Temp1 the value 123456 (data of Temp2). Could someone please let me know where I'm going wrong in my Go code?

Thanks!

Upvotes: 0

Views: 339

Answers (1)

lmars
lmars

Reputation: 2532

I suggest putting the actual config values in a field on the Config struct which is mutated under the lock, rather than mutating the Config pointer, because as you are encountering callers of the method will still have a reference to the old pointer.

For example:

type Config struct {
    values map[string]interface{} // or whatever is appropriate for your config
    lock   sync.RWMutex
}

func (c *Config) Get(k string) (interface{}, bool) {
    c.lock.RLock()
    defer c.lock.RUnlock()
    v, ok := c.values[k]
    return v, ok
}

func (c *Config) Reload(path string) error {
    newConfig, err := LoadFromFile(path)
    if err != nil {
        return err
    }
    c.lock.Lock()
    defer c.lock.Unlock()
    c.values = newConfig.values
    return nil
}

Upvotes: 1

Related Questions