Viper: String Slices from pflags are not handled correctly by viper.

Created on 12 Jun 2016  路  6Comments  路  Source: spf13/viper

The slice of strings just contains one element that is the stringified version of the string
ie: []string{"[firstarg,secondarg]"}
or in the case of nil/empty: []string{"[]"}

It appears that this is coming from the Pflag libraries ValueString() function. I've included a patch that "helps" the issue but I suspect it's a little bit more deep-seated as the cast package also doesn't seem to handle this case well at all hence I'm not making trying to make a PR for this.

For others hitting this issue the workaround is to simply use pflags directly for string slices until this is fixed.

diff --git a/viper.go b/viper.go
index a2633b0..d1cce44 100644
--- a/viper.go
+++ b/viper.go
@@ -479,6 +479,8 @@ func (v *Viper) Get(key string) interface{} {
                                val = cast.ToInt(flag.ValueString())
                        case "bool":
                                val = cast.ToBool(flag.ValueString())
+                       case "stringSlice":
+                               val = []string{}
                        default:
                                val = flag.ValueString()
                        }
@@ -742,6 +744,8 @@ func (v *Viper) find(key string) interface{} {
                        return cast.ToInt(flag.ValueString())
                case "bool":
                        return cast.ToBool(flag.ValueString())
+               case "stringSlice":
+                       return strings.Split(strings.Trim(flag.ValueString(), "[]"), ",")
                default:
                        return flag.ValueString()
                }

Example program that shows the the failure:

package main

import (
    "fmt"
    "os"

    "github.com/davecgh/go-spew/spew"
    "github.com/spf13/cobra"
    "github.com/spf13/viper"
)

func main() {
    var rootCmd = &cobra.Command{
        Run: run,
    }

    rootCmd.PersistentFlags().StringSliceP("thing", "t", nil, "")
    viper.BindPFlags(rootCmd.PersistentFlags())

    if err := rootCmd.Execute(); err != nil {
        fmt.Printf("\n%+v\n", err)
        os.Exit(1)
    }
}

func run(cmd *cobra.Command, args []string) {
    str := viper.Get("thing")
    slice := viper.GetStringSlice("thing")
    slicePFlag, _ := cmd.PersistentFlags().GetStringSlice("thing")

    spew.Dump(str, slice, slicePFlag)
}

Output (annotated for clarity) of go run main.go

str   = (string) (len=2) "[]"
slice = ([]string) (len=1 cap=1) {
 (string) (len=2) "[]"
}
slicePFlag = ([]string) {}

Output (annotated for clarity) of go run main.go -t thing1 -t thing2

str   = (string) (len=15) "[thing1,thing2]"
slice = ([]string) (len=1 cap=1) {
 (string) (len=15) "[thing1,thing2]"
}
slicePFlag = ([]string) (len=2 cap=2) {
 (string) (len=6) "thing1",
 (string) (len=6) "thing2"
}

Most helpful comment

@dansteen The issue is there. In my pull request I've added a test and fix.

All 6 comments

cc @bep

Hi, just wondering whats the status of this issue? Is this the recommended workaround?

@aarondl,

PR #244 submitted:

$ go run main.go 
([]string) {
}
([]string) {
}
([]string) {
}

$ go run main.go -t thing1 -t thing2
([]string) (len=2 cap=2) {
 (string) (len=6) "thing1",
 (string) (len=6) "thing2"
}
([]string) (len=2 cap=2) {
 (string) (len=6) "thing1",
 (string) (len=6) "thing2"
}
([]string) (len=2 cap=2) {
 (string) (len=6) "thing1",
 (string) (len=6) "thing2"
}

240 might fix this, will check.

The latest master still seems to have this problem:

$ go run foo.go --thing test --thing test
(string) (len=9) "test,test"
([]string) (len=1 cap=1) {
 (string) (len=9) "test,test"
}
([]string) (len=2 cap=2) {
 (string) (len=4) "test",
 (string) (len=4) "test"
}

I have this issue as well. I am also using the latest version.

@dansteen The issue is there. In my pull request I've added a test and fix.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xh3b4sd picture xh3b4sd  路  6Comments

kwk picture kwk  路  5Comments

gmaxwell94 picture gmaxwell94  路  5Comments

noandrea picture noandrea  路  4Comments

michaeleekk picture michaeleekk  路  3Comments