code: func UnmarshalAppConfig(cfg interface{}, v *viper.Viper) error {
  	err := v.Unmarshal(cfg)
  	if err != nil {
  		return err
  	}
  
  	val := reflect.Indirect(reflect.ValueOf(cfg))
  
  	// if cfg has an imbedded AppConfig then we need to unmarshal
  	// directly into that and overwrite it in the parent struct,
  	// since its another layer of indirection and viper
  	// can't handle it magically.
  	for i := 0; i < val.NumField(); i++ {
  		appCfg, ok := val.Field(i).Interface().(AppConfig)
  		if !ok {
  			continue
  		}
  
  		v.Unmarshal(&appCfg)
  		val.Field(i).Set(reflect.ValueOf(appCfg))
  		// overwrite val to point to the AppConfig so DBConfig can be set below.
  		val = val.Field(i)
  		break
  	}
  
  	// Find *DBConfig and set object appropriately
  	for i := 0; i < val.NumField(); i++ {
  		dbCfg, ok := val.Field(i).Interface().(DBConfig)
  		if !ok {
  			continue
  		}
  
  		if dbCfg.DB == "postgres" {
  			if dbCfg.Port == 0 {
  				dbCfg.Port = 5432
  			}
  			if dbCfg.SSLMode == "" {
  				dbCfg.SSLMode = "require"
  			}
  		} else if dbCfg.DB == "mysql" {
  			if dbCfg.Port == 0 {
  				dbCfg.Port = 3306
  			}
  			if dbCfg.SSLMode == "" {
  				dbCfg.SSLMode = "true"
  			}
  		}
  
  		val.Field(i).Set(reflect.ValueOf(dbCfg))
  
  		// Finished working on the db cfg struct, so break out
  		break
  	}
  
  	return nil
  }
docs: // UnmarshalAppConfig unmarshals the viper's configured config file
  // into the passed in cfg object containing an AppConfig