Skip to content

Nested . separated flags with common prefix not working with pflag in Viper >= 1.18.0 #1922

@shani1998

Description

@shani1998

Preflight Checklist

  • I have searched the issue tracker for an issue that matches the one I want to file, without success.
  • I am not looking for support or already pursued the available support channels without success.
  • I have checked the troubleshooting guide for my problem, without success.

Viper Version

1.18.0

Go Version

1.22.6

Config Source

Flags

Format

Other (specify below)

Repl.it link

No response

Code reproducing the issue

package main

import (
	"fmt"

	"github.com/spf13/pflag"
	"github.com/spf13/viper"
)

var (
	_ = pflag.String("gateway.endpoint.v1", "some/path/v1", "endpoint of gateway server v2")
	_ = pflag.String("gateway.endpoint", "some/path/", "endpoint of gateway server v3")
)

func init() {
	pflag.Parse()
	viper.BindPFlags(pflag.CommandLine)
	viper.AutomaticEnv()
}

func main() {
	fmt.Println("viper.GetString(\"gateway.endpoint\"):", viper.GetString("gateway.endpoint"))
	fmt.Println("viper.GetString(\"gateway.endpoint.v1\"):", viper.GetString("gateway.endpoint.v1")) // getting empty 
}
got output for this:
viper.GetString("gateway.endpoint"): some/path/
viper.GetString("gateway.endpoint.v1"):

Expected Behavior

it should print:

~ go run test.go                                                                    
viper.GetString("gateway.endpoint"): some/path/
viper.GetString("gateway.endpoint.v1"): some/path/v1

Actual Behavior

in v1.17.0
it is working as expected
returning output as

~ go run test.go                                                                    
viper.GetString("gateway.endpoint"): some/path/
viper.GetString("gateway.endpoint.v1"): some/path/v1

Steps To Reproduce

 ✗ go env                                                                                  
GO111MODULE=''
GOARCH='arm64'
GOBIN=''
GOCACHE='/Users/spahk/Library/Caches/go-build'
GOENV='/Users/spahk/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFLAGS=''
GOHOSTARCH='arm64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMODCACHE='/Users/spahk/go/pkg/mod'
GONOPROXY=''
GONOSUMDB=''
GOOS='darwin'
GOPATH='/Users/spahk/go'
GOPRIVATE=''
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/opt/homebrew/Cellar/go/1.22.4/libexec'
GOSUMDB='sum.golang.org'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/opt/homebrew/Cellar/go/1.22.4/libexec/pkg/tool/darwin_arm64'
GOVCS=''
GOVERSION='go1.22.4'
GCCGO='gccgo'
AR='ar'
CC='cc'
CXX='c++'
CGO_ENABLED='1'
GOMOD='/Users/spahk/projects/test/go.mod'
GOWORK=''
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
PKG_CONFIG='pkg-config'
GOGCCFLAGS='-fPIC -arch arm64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/jx/dpklpdss291clqs9t6xrh0c00000gp/T/go-build851702384=/tmp/go-build -gno-record-gcc-switches -fno-common'

go mod

module test

go 1.22.4

require (
	github.com/spf13/pflag v1.0.5
	github.com/spf13/viper v1.18.0
)

require (
	github.com/fsnotify/fsnotify v1.7.0 // indirect
	github.com/hashicorp/hcl v1.0.0 // indirect
	github.com/magiconair/properties v1.8.7 // indirect
	github.com/mitchellh/mapstructure v1.5.0 // indirect
	github.com/pelletier/go-toml/v2 v2.2.2 // indirect
	github.com/sagikazarmark/locafero v0.4.0 // indirect
	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
	github.com/sourcegraph/conc v0.3.0 // indirect
	github.com/spf13/afero v1.11.0 // indirect
	github.com/spf13/cast v1.6.0 // indirect
	github.com/subosito/gotenv v1.6.0 // indirect
	go.uber.org/atomic v1.9.0 // indirect
	go.uber.org/multierr v1.9.0 // indirect
	golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
	golang.org/x/sys v0.18.0 // indirect
	golang.org/x/text v0.14.0 // indirect
	gopkg.in/ini.v1 v1.67.0 // indirect
	gopkg.in/yaml.v3 v3.0.1 // indirect
)

Additional Information

Updated:
I can see it is working with another nested flags like _ = pflag.String("a.b.c.d.v1", "some/path/abc", "endpoint of gateway server v4")
but i am wondering what is the special with key gateway.endpoint.*

Metadata

Metadata

Assignees

No one assigned

    Labels

    kind/bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions