diff --git a/.idea/markdown.xml b/.idea/markdown.xml
new file mode 100644
index 0000000000000000000000000000000000000000..ec0b30fa7ea2824af6923493653e32595b0907a8
--- /dev/null
+++ b/.idea/markdown.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="MarkdownSettings">
+    <enabledExtensions>
+      <entry key="MermaidLanguageExtension" value="false" />
+      <entry key="PlantUMLLanguageExtension" value="true" />
+    </enabledExtensions>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000000000000000000000000000000000000..639900d13c6182e452e33a3bd638e70a0146c785
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectRootManager">
+    <output url="file://$PROJECT_DIR$/out" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/modules.xml b/.idea/modules.xml
new file mode 100644
index 0000000000000000000000000000000000000000..921c18fcf853bd017944147bb2073b01d3561cdf
--- /dev/null
+++ b/.idea/modules.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="ProjectModuleManager">
+    <modules>
+      <module fileurl="file://$PROJECT_DIR$/.idea/pathfinder.iml" filepath="$PROJECT_DIR$/.idea/pathfinder.iml" />
+    </modules>
+  </component>
+</project>
\ No newline at end of file
diff --git a/.idea/pathfinder.iml b/.idea/pathfinder.iml
new file mode 100644
index 0000000000000000000000000000000000000000..25ed3f6e7b6e344b6ca91ebcc5d005f35357f9cf
--- /dev/null
+++ b/.idea/pathfinder.iml
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+  <component name="Go" enabled="true" />
+  <component name="NewModuleRootManager" inherit-compiler-output="true">
+    <exclude-output />
+    <content url="file://$MODULE_DIR$" />
+    <orderEntry type="inheritedJdk" />
+    <orderEntry type="sourceFolder" forTests="false" />
+  </component>
+</module>
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000000000000000000000000000000000000..35eb1ddfbbc029bcab630581847471d7f238ec53
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project version="4">
+  <component name="VcsDirectoryMappings">
+    <mapping directory="" vcs="Git" />
+  </component>
+</project>
\ No newline at end of file
diff --git a/get.go b/get.go
index c8f6603bfa66a679e8956131ae7aef109404cd0d..90c2b1cc25a621455263d8abd8e48844ecf1fcdd 100644
--- a/get.go
+++ b/get.go
@@ -9,7 +9,10 @@ import (
 	"strings"
 )
 
-// This function returns the value of a field in a struct, given a path to the field.
+// GetValue returns the value of a field in a struct, given a path to the field.
+// The path can contain dots to access nested fields.
+// The object must be a pointer to a struct, a struct, a map, a slice or an array,
+// otherwise an error is returned.
 func GetValue[D any](obj D, keyWithDots string) (any, error) {
 	keySlice := strings.Split(keyWithDots, ".")
 	v := reflect.ValueOf(obj)
diff --git a/go.mod b/go.mod
index 047406f2c4ec9cbb01044b91112e198c4f7a6877..f1f0841c1e1bef35c1eea035cb525543cae38066 100644
--- a/go.mod
+++ b/go.mod
@@ -4,6 +4,7 @@ go 1.20
 
 require (
 	github.com/davecgh/go-spew v1.1.1 // indirect
+	github.com/google/gofuzz v1.2.0 // indirect
 	github.com/pmezard/go-difflib v1.0.0 // indirect
 	github.com/stretchr/testify v1.8.0 // indirect
 	gopkg.in/yaml.v3 v3.0.1 // indirect
diff --git a/go.sum b/go.sum
index b410979a43764db2bd7f77cc065eb839b7d20181..0a45411e2f82b7c821a164bde55de7be4998bd2a 100644
--- a/go.sum
+++ b/go.sum
@@ -1,6 +1,8 @@
 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
+github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
diff --git a/issue_2_test.go b/issue_2_test.go
index 4be4bec9b40bf9ca2bb3ed49e1dca51f8899d7dd..1e3ef823e19040d00619cb9e2d29a2fc8b449d84 100644
--- a/issue_2_test.go
+++ b/issue_2_test.go
@@ -5,6 +5,7 @@ package pathfinder
 
 import (
 	"fmt"
+	"github.com/google/gofuzz"
 	"github.com/stretchr/testify/assert"
 	"testing"
 )
@@ -22,7 +23,7 @@ type Issue2Struct struct {
 }
 
 func TestGetValueWithArray(t *testing.T) {
-	invalidValue := Issue2Struct{
+	testStructForGet := Issue2Struct{
 		Issue1Sub1: Issue2SubStruct{
 			Issue2SubField: Issue2SubSubStruct{
 				Issue2SubSubField: []string{"test0", "test1", "test2"},
@@ -32,16 +33,76 @@ func TestGetValueWithArray(t *testing.T) {
 
 	// iterate from 0 to 2
 	for i := 0; i < 2; i++ {
-		result, err := GetValue(invalidValue, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", i))
+		result, err := GetValue(testStructForGet, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", i))
 
 		assert.Nil(t, err)
 		assert.Equal(t, result, "test"+fmt.Sprintf("%d", i))
 	}
 
 	i := 3
-	result, err := GetValue(invalidValue, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", i))
+	result, err := GetValue(testStructForGet, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", i))
 
 	assert.NotNil(t, err)
 	assert.Nil(t, result)
 
 }
+
+func TestGetValueWithArrayFuzz(t *testing.T) {
+	f := fuzz.New()
+
+	testStructForGet := Issue2Struct{
+		Issue1Sub1: Issue2SubStruct{
+			Issue2SubField: Issue2SubSubStruct{
+				Issue2SubSubField: []string{"test0", "test1", "test2"},
+			},
+		},
+	}
+
+	for i := 0; i < 100; i++ {
+		var randomIndex int
+		f.Fuzz(&randomIndex)
+		randomIndex = randomIndex % len(testStructForGet.Issue1Sub1.Issue2SubField.Issue2SubSubField)
+		if randomIndex < 0 {
+			randomIndex = -randomIndex
+		}
+
+		result, err := GetValue(testStructForGet, "Issue1Sub1.Issue2SubField.Issue2SubSubField."+fmt.Sprintf("%d", randomIndex))
+
+		if randomIndex < 3 {
+			assert.Nil(t, err)
+			assert.Equal(t, result, "test"+fmt.Sprintf("%d", randomIndex))
+		} else {
+			assert.NotNil(t, err)
+			assert.Nil(t, result)
+		}
+	}
+}
+
+func TestSetValueWithArray(t *testing.T) {
+	testStructForSet := Issue2Struct{
+		Issue1Sub1: Issue2SubStruct{
+			Issue2SubField: Issue2SubSubStruct{
+				Issue2SubSubField: []string{"test0", "test1", "test2"},
+			},
+		},
+	}
+
+	// iterate from 0 to 2
+	for i := 0; i < 2; i++ {
+
+		newValue := "test~~" + fmt.Sprintf("%d", i)
+		k := "Issue1Sub1.Issue2SubField.Issue2SubSubField." + fmt.Sprintf("%d", i)
+		err := SetValue(&testStructForSet, k, newValue)
+
+		assert.Nil(t, err)
+
+		result, err := GetValue(testStructForSet, k)
+		assert.Equal(t, result, newValue)
+	}
+
+	i := 3
+	k := "Issue1Sub1.Issue2SubField.Issue2SubSubField." + fmt.Sprintf("%d", i)
+	err := SetValue(testStructForSet, k, "test3")
+	assert.NotNil(t, err)
+
+}
diff --git a/set.go b/set.go
index f5ca2f43314c861ad15eeb3abcf15d50c3463f31..fa7443a85a4b32aea8cfe26ae3f9e89ec5b03624 100644
--- a/set.go
+++ b/set.go
@@ -10,7 +10,8 @@ import (
 	"strings"
 )
 
-// This function sets the value of a field in a struct, given a path to the field.
+// SetValue sets the value of a field in a struct, given a path to the field.
+// The object must be a pointer to a struct, otherwise an error is returned.
 func SetValue[D any](obj D, keyWithDots string, newValue any) error {
 
 	keySlice := strings.Split(keyWithDots, ".")
@@ -21,7 +22,13 @@ func SetValue[D any](obj D, keyWithDots string, newValue any) error {
 			if v.Kind() == reflect.Invalid {
 				return newInvalidPathError(keyWithDots)
 			}
-			v = v.Addr()
+
+			if v.CanAddr() {
+				v = v.Addr()
+			} else {
+				return newCannotSetError(keyWithDots)
+			}
+
 		}
 
 		if v.Kind() != reflect.Ptr {
@@ -46,20 +53,37 @@ func SetValue[D any](obj D, keyWithDots string, newValue any) error {
 	}
 
 	// non-supporter type at the top of the path
-	if v.Kind() != reflect.Struct {
+	switch v.Kind() {
+	case reflect.Struct:
+
+		v = v.FieldByName(keySlice[len(keySlice)-1])
+		if !v.IsValid() {
+			return newInvalidPathError(keyWithDots)
+		}
+
+		if !v.CanSet() {
+			return newCannotSetError(keyWithDots)
+		}
+
+	case reflect.Map:
 		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
-	}
+	case reflect.Slice:
 
-	v = v.FieldByName(keySlice[len(keySlice)-1])
-	if !v.IsValid() {
-		return newInvalidPathError(keyWithDots)
-	}
+		// index is a number and get v from slice with index
+		index, err := strconv.Atoi(keySlice[len(keySlice)-1])
+		if err != nil {
+			return newInvalidPathError(keyWithDots)
+		}
 
-	if !v.CanSet() {
-		return newCannotSetError(keyWithDots)
-	}
+		// index out of range
+		if index >= v.Len() {
+			return newInvalidPathError(keyWithDots)
+		}
 
-	switch v.Kind() {
+		v = v.Index(index)
+
+	case reflect.Array:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
 	case reflect.Ptr:
 		if newValue == nil {
 			v.Set(reflect.Zero(v.Type()))
@@ -67,6 +91,24 @@ func SetValue[D any](obj D, keyWithDots string, newValue any) error {
 			v.Set(reflect.ValueOf(&newValue))
 		}
 		return nil
+	case reflect.Interface:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.Chan:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.Func:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.UnsafePointer:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.Uintptr:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.Complex64:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.Complex128:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	case reflect.Invalid:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
+	default:
+		return newUnsupportedTypeAtTopOfPathError(keyWithDots, v.Type())
 	}
 
 	newValueType := reflect.TypeOf(newValue)