diff --git a/README.md b/README.md
index f211b06..857588a 100644
--- a/README.md
+++ b/README.md
@@ -667,8 +667,7 @@ If you want to unmarshal configuration where the keys themselves contain dot (th
 you have to change the delimiter:
 
 ```go
-v := viper.New()
-v.SetKeyDelimiter("::")
+v := viper.NewWithOptions(viper.KeyDelimiter("::"))
 
 v.SetDefault("chart::values", map[string]interface{}{
     "ingress": map[string]interface{}{
diff --git a/viper.go b/viper.go
index 0e3eeaf..dcfd2b0 100644
--- a/viper.go
+++ b/viper.go
@@ -236,6 +236,39 @@ func New() *Viper {
 	return v
 }
 
+// Option configures Viper using the functional options paradigm popularized by Rob Pike and Dave Cheney.
+// If you're unfamiliar with this style,
+// see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and
+// https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis.
+type Option interface {
+	apply(v *Viper)
+}
+
+type optionFunc func(v *Viper)
+
+func (fn optionFunc) apply(v *Viper) {
+	fn(v)
+}
+
+// KeyDelimiter sets the delimiter used for determining key parts.
+// By default it's value is ".".
+func KeyDelimiter(d string) Option {
+	return optionFunc(func(v *Viper) {
+		v.keyDelim = d
+	})
+}
+
+// NewWithOptions creates a new Viper instance.
+func NewWithOptions(opts ...Option) *Viper {
+	v := New()
+
+	for _, opt := range opts {
+		opt.apply(v)
+	}
+
+	return v
+}
+
 // Reset is intended for testing, will reset all to default settings.
 // In the public interface for the viper package so applications
 // can use it in their testing as well.
@@ -245,15 +278,6 @@ func Reset() {
 	SupportedRemoteProviders = []string{"etcd", "consul"}
 }
 
-// SetKeyDelimiter sets the delimiter used for determining key parts.
-// By default it's value is ".".
-func SetKeyDelimiter(keyDelim string) { v.SetKeyDelimiter(keyDelim) }
-func (v *Viper) SetKeyDelimiter(keyDelim string) {
-	if keyDelim != "" {
-		v.keyDelim = keyDelim
-	}
-}
-
 type defaultRemoteProvider struct {
 	provider      string
 	endpoint      string
diff --git a/viper_test.go b/viper_test.go
index baf0998..9f4dff3 100644
--- a/viper_test.go
+++ b/viper_test.go
@@ -2029,9 +2029,8 @@ emails:
     active: true
 `)
 
-func TestSetKeyDelimiter(t *testing.T) {
-	v := New()
-	v.SetKeyDelimiter("::")
+func TestKeyDelimiter(t *testing.T) {
+	v := NewWithOptions(KeyDelimiter("::"))
 	v.SetConfigType("yaml")
 	r := strings.NewReader(string(yamlExampleWithDot))