Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Diffing struct with private field fails #18

Closed
Gallardot opened this issue Oct 10, 2019 · 1 comment · Fixed by #19
Closed

Diffing struct with private field fails #18

Gallardot opened this issue Oct 10, 2019 · 1 comment · Fixed by #19

Comments

@Gallardot
Copy link

the example code

package main

import (
	"github.com/r3labs/diff"
	"log"
)

type int64Amount struct {
	A int64
	b int64
}

func main() {
	changelog, err := diff.Diff(int64Amount{A: 1}, int64Amount{A: 2})
	log.Println(changelog, err)

	// will get panic
	changelog, err = diff.Diff(int64Amount{b: 2}, int64Amount{b: 3})
	log.Println(changelog, err)
}

we will get a panic

panic: reflect.Value.Interface: cannot return value obtained from unexported field or method

because the field b is a private field. can not execute 'Interface()' methods.

for example on diffInt

func (d *Differ) diffInt(path []string, a, b reflect.Value) error {
	if a.Kind() == reflect.Invalid {
		d.cl.add(CREATE, path, nil, b.Interface())
		return nil
	}

	if b.Kind() == reflect.Invalid {
		d.cl.add(DELETE, path, a.Interface(), nil)
		return nil
	}

	if a.Kind() != b.Kind() {
		return ErrTypeMismatch
	}

	if a.Int() != b.Int() {
		d.cl.add(UPDATE, path, a.Interface(), b.Interface())
	}

	return nil
}

If we sure know the kind is Int, we can use Int() to get the value
I think do some change is a good idea

         if a.Int() != b.Int() {
		d.cl.add(UPDATE, path, a.Int(), b.Int())
	}
@purehyperbole
Copy link
Member

Thanks for raising the issue.

I've implemented the changes you suggested on the private-field-support branch. Would you please be able to test and see if it behaves as you expect?

One thing to note, calling a.Int() always returns an int64, regardless of whether the underling type is an int, int32, int16, etc.

Therefore, in order to prevent unexpected changes for other users, it only calls a.Int() as a fallback if the field is private.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants