add a new type StringArray
diff --git a/flag.go b/flag.go
index eb143d7..c28f3bd 100644
--- a/flag.go
+++ b/flag.go
@@ -434,7 +434,7 @@
 		return f.DefValue == ""
 	case *ipValue, *ipMaskValue, *ipNetValue:
 		return f.DefValue == "<nil>"
-	case *intSliceValue, *stringSliceValue:
+	case *intSliceValue, *stringSliceValue, *stringArrayValue:
 		return f.DefValue == "[]"
 	default:
 		return true
diff --git a/flag_test.go b/flag_test.go
index 86b37e5..1befb94 100644
--- a/flag_test.go
+++ b/flag_test.go
@@ -874,23 +874,24 @@
 	}
 }
 
-const defaultOutput = `      --A                     for bootstrapping, allow 'any' type
-      --Alongflagname         disable bounds checking
-  -C, --CCC                   a boolean defaulting to true (default true)
-      --D path                set relative path for local imports
-      --F number              a non-zero number (default 2.7)
-      --G float               a float that defaults to zero
-      --IP ip                 IP address with no default
-      --IPMask ipMask         Netmask address with no default
-      --IPNet ipNet           IP network with no default
-      --Ints intSlice         int slice with zero default
-      --N int                 a non-zero int (default 27)
-      --ND1 string[="bar"]    a string with NoOptDefVal (default "foo")
-      --ND2 num[=4321]        a num with NoOptDefVal (default 1234)
-      --Strings stringSlice   string slice with zero default
-      --Z int                 an int that defaults to zero
-      --custom custom         custom Value implementation
-      --maxT timeout          set timeout for dial
+const defaultOutput = `      --A                         for bootstrapping, allow 'any' type
+      --Alongflagname             disable bounds checking
+  -C, --CCC                       a boolean defaulting to true (default true)
+      --D path                    set relative path for local imports
+      --F number                  a non-zero number (default 2.7)
+      --G float                   a float that defaults to zero
+      --IP ip                     IP address with no default
+      --IPMask ipMask             Netmask address with no default
+      --IPNet ipNet               IP network with no default
+      --Ints intSlice             int slice with zero default
+      --N int                     a non-zero int (default 27)
+      --ND1 string[="bar"]        a string with NoOptDefVal (default "foo")
+      --ND2 num[=4321]            a num with NoOptDefVal (default 1234)
+      --StringArray stringArray   string array with zero default
+      --StringSlice stringSlice   string slice with zero default
+      --Z int                     an int that defaults to zero
+      --custom custom             custom Value implementation
+      --maxT timeout              set timeout for dial
 `
 
 // Custom value that satisfies the Value interface.
@@ -927,7 +928,8 @@
 	fs.Lookup("ND1").NoOptDefVal = "bar"
 	fs.Int("ND2", 1234, "a `num` with NoOptDefVal")
 	fs.Lookup("ND2").NoOptDefVal = "4321"
-	fs.StringSlice("Strings", []string{}, "string slice with zero default")
+	fs.StringSlice("StringSlice", []string{}, "string slice with zero default")
+	fs.StringArray("StringArray", []string{}, "string array with zero default")
 
 	var cv customValue
 	fs.Var(&cv, "custom", "custom Value implementation")
diff --git a/string_array.go b/string_array.go
new file mode 100644
index 0000000..f320f2e
--- /dev/null
+++ b/string_array.go
@@ -0,0 +1,110 @@
+package pflag
+
+import (
+	"fmt"
+	"strings"
+)
+
+var _ = fmt.Fprint
+
+// -- stringArray Value
+type stringArrayValue struct {
+	value   *[]string
+	changed bool
+}
+
+func newStringArrayValue(val []string, p *[]string) *stringArrayValue {
+	ssv := new(stringArrayValue)
+	ssv.value = p
+	*ssv.value = val
+	return ssv
+}
+
+func (s *stringArrayValue) Set(val string) error {
+	if !s.changed {
+		*s.value = []string{val}
+		s.changed = true
+	} else {
+		*s.value = append(*s.value, val)
+	}
+	return nil
+}
+
+func (s *stringArrayValue) Type() string {
+	return "stringArray"
+}
+
+func (s *stringArrayValue) String() string {
+	str, _ := writeAsCSV(*s.value)
+	return "[" + str + "]"
+}
+
+func stringArrayConv(sval string) (interface{}, error) {
+	sval = strings.Trim(sval, "[]")
+	// An empty string would cause a array with one (empty) string
+	if len(sval) == 0 {
+		return []string{}, nil
+	}
+	return readAsCSV(sval)
+}
+
+// GetStringArray return the []string value of a flag with the given name
+func (f *FlagSet) GetStringArray(name string) ([]string, error) {
+	val, err := f.getFlagType(name, "stringArray", stringArrayConv)
+	if err != nil {
+		return []string{}, err
+	}
+	return val.([]string), nil
+}
+
+// StringArrayVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a []string variable in which to store the values of the multiple flags.
+// The value of each argument will not try to be separated by comma
+func (f *FlagSet) StringArrayVar(p *[]string, name string, value []string, usage string) {
+	f.VarP(newStringArrayValue(value, p), name, "", usage)
+}
+
+// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
+	f.VarP(newStringArrayValue(value, p), name, shorthand, usage)
+}
+
+// StringArrayVar defines a string flag with specified name, default value, and usage string.
+// The argument p points to a []string variable in which to store the value of the flag.
+// The value of each argument will not try to be separated by comma
+func StringArrayVar(p *[]string, name string, value []string, usage string) {
+	CommandLine.VarP(newStringArrayValue(value, p), name, "", usage)
+}
+
+// StringArrayVarP is like StringArrayVar, but accepts a shorthand letter that can be used after a single dash.
+func StringArrayVarP(p *[]string, name, shorthand string, value []string, usage string) {
+	CommandLine.VarP(newStringArrayValue(value, p), name, shorthand, usage)
+}
+
+// StringArray defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a []string variable that stores the value of the flag.
+// The value of each argument will not try to be separated by comma
+func (f *FlagSet) StringArray(name string, value []string, usage string) *[]string {
+	p := []string{}
+	f.StringArrayVarP(&p, name, "", value, usage)
+	return &p
+}
+
+// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
+func (f *FlagSet) StringArrayP(name, shorthand string, value []string, usage string) *[]string {
+	p := []string{}
+	f.StringArrayVarP(&p, name, shorthand, value, usage)
+	return &p
+}
+
+// StringArray defines a string flag with specified name, default value, and usage string.
+// The return value is the address of a []string variable that stores the value of the flag.
+// The value of each argument will not try to be separated by comma
+func StringArray(name string, value []string, usage string) *[]string {
+	return CommandLine.StringArrayP(name, "", value, usage)
+}
+
+// StringArrayP is like StringArray, but accepts a shorthand letter that can be used after a single dash.
+func StringArrayP(name, shorthand string, value []string, usage string) *[]string {
+	return CommandLine.StringArrayP(name, shorthand, value, usage)
+}
diff --git a/string_array_test.go b/string_array_test.go
new file mode 100644
index 0000000..3e3eb74
--- /dev/null
+++ b/string_array_test.go
@@ -0,0 +1,194 @@
+// Copyright 2009 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package pflag
+
+import (
+	"fmt"
+	"testing"
+)
+
+func setUpSAFlagSet(sap *[]string) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringArrayVar(sap, "sa", []string{}, "Command separated list!")
+	return f
+}
+
+func setUpSAFlagSetWithDefault(sap *[]string) *FlagSet {
+	f := NewFlagSet("test", ContinueOnError)
+	f.StringArrayVar(sap, "sa", []string{"default", "values"}, "Command separated list!")
+	return f
+}
+
+func TestEmptySA(t *testing.T) {
+	var sa []string
+	f := setUpSAFlagSet(&sa)
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getSA, err := f.GetStringArray("sa")
+	if err != nil {
+		t.Fatal("got an error from GetStringArray():", err)
+	}
+	if len(getSA) != 0 {
+		t.Fatalf("got sa %v with len=%d but expected length=0", getSA, len(getSA))
+	}
+}
+
+func TestEmptySAValue(t *testing.T) {
+	var sa []string
+	f := setUpSAFlagSet(&sa)
+	err := f.Parse([]string{"--sa="})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	getSA, err := f.GetStringArray("sa")
+	if err != nil {
+		t.Fatal("got an error from GetStringArray():", err)
+	}
+	if len(getSA) != 0 {
+		t.Fatalf("got sa %v with len=%d but expected length=0", getSA, len(getSA))
+	}
+}
+
+func TestSADefault(t *testing.T) {
+	var sa []string
+	f := setUpSAFlagSetWithDefault(&sa)
+
+	vals := []string{"default", "values"}
+
+	err := f.Parse([]string{})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+	for i, v := range sa {
+		if vals[i] != v {
+			t.Fatalf("expected sa[%d] to be %s but got: %s", i, vals[i], v)
+		}
+	}
+
+	getSA, err := f.GetStringArray("sa")
+	if err != nil {
+		t.Fatal("got an error from GetStringArray():", err)
+	}
+	for i, v := range getSA {
+		if vals[i] != v {
+			t.Fatalf("expected sa[%d] to be %s from GetStringArray but got: %s", i, vals[i], v)
+		}
+	}
+}
+
+func TestSAWithDefault(t *testing.T) {
+	var sa []string
+	f := setUpSAFlagSetWithDefault(&sa)
+
+	val := "one"
+	arg := fmt.Sprintf("--sa=%s", val)
+	err := f.Parse([]string{arg})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	if len(sa) != 1 {
+		t.Fatalf("expected number of values to be %d but %d", 1, len(sa))
+	}
+
+	if sa[0] != val {
+		t.Fatalf("expected value to be %s but got: %s", sa[0], val)
+	}
+
+	getSA, err := f.GetStringArray("sa")
+	if err != nil {
+		t.Fatal("got an error from GetStringArray():", err)
+	}
+
+	if len(getSA) != 1 {
+		t.Fatalf("expected number of values to be %d but %d", 1, len(getSA))
+	}
+
+	if getSA[0] != val {
+		t.Fatalf("expected value to be %s but got: %s", getSA[0], val)
+	}
+}
+
+func TestSACalledTwice(t *testing.T) {
+	var sa []string
+	f := setUpSAFlagSet(&sa)
+
+	in := []string{"one", "two"}
+	expected := []string{"one", "two"}
+	argfmt := "--sa=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	err := f.Parse([]string{arg1, arg2})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	if len(expected) != len(sa) {
+		t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa))
+	}
+	for i, v := range sa {
+		if expected[i] != v {
+			t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v)
+		}
+	}
+
+	values, err := f.GetStringArray("sa")
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	if len(expected) != len(values) {
+		t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(sa))
+	}
+	for i, v := range values {
+		if expected[i] != v {
+			t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v)
+		}
+	}
+}
+
+func TestSAWithSpecialChar(t *testing.T) {
+	var sa []string
+	f := setUpSAFlagSet(&sa)
+
+	in := []string{"one,two", `"three"`, `"four,five",six`, "seven eight"}
+	expected := []string{"one,two", `"three"`, `"four,five",six`, "seven eight"}
+	argfmt := "--sa=%s"
+	arg1 := fmt.Sprintf(argfmt, in[0])
+	arg2 := fmt.Sprintf(argfmt, in[1])
+	arg3 := fmt.Sprintf(argfmt, in[2])
+	arg4 := fmt.Sprintf(argfmt, in[3])
+	err := f.Parse([]string{arg1, arg2, arg3, arg4})
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	if len(expected) != len(sa) {
+		t.Fatalf("expected number of sa to be %d but got: %d", len(expected), len(sa))
+	}
+	for i, v := range sa {
+		if expected[i] != v {
+			t.Fatalf("expected sa[%d] to be %s but got: %s", i, expected[i], v)
+		}
+	}
+
+	values, err := f.GetStringArray("sa")
+	if err != nil {
+		t.Fatal("expected no error; got", err)
+	}
+
+	if len(expected) != len(values) {
+		t.Fatalf("expected number of values to be %d but got: %d", len(expected), len(values))
+	}
+	for i, v := range values {
+		if expected[i] != v {
+			t.Fatalf("expected got sa[%d] to be %s but got: %s", i, expected[i], v)
+		}
+	}
+}
diff --git a/string_slice.go b/string_slice.go
index 927a440..51e3c5d 100644
--- a/string_slice.go
+++ b/string_slice.go
@@ -31,6 +31,17 @@
 	return csvReader.Read()
 }
 
+func writeAsCSV(vals []string) (string, error) {
+	b := &bytes.Buffer{}
+	w := csv.NewWriter(b)
+	err := w.Write(vals)
+	if err != nil {
+		return "", err
+	}
+	w.Flush()
+	return strings.TrimSuffix(b.String(), fmt.Sprintln()), nil
+}
+
 func (s *stringSliceValue) Set(val string) error {
 	v, err := readAsCSV(val)
 	if err != nil {
@@ -50,11 +61,8 @@
 }
 
 func (s *stringSliceValue) String() string {
-	b := &bytes.Buffer{}
-	w := csv.NewWriter(b)
-	w.Write(*s.value)
-	w.Flush()
-	return "[" + strings.TrimSuffix(b.String(), fmt.Sprintln()) + "]"
+	str, _ := writeAsCSV(*s.value)
+	return "[" + str + "]"
 }
 
 func stringSliceConv(sval string) (interface{}, error) {