goset icon indicating copy to clipboard operation
goset copied to clipboard

About Pointer value compare

Open cylonchau opened this issue 1 year ago • 4 comments

Hey Amit Itzkovitch!

I have a struct value is pointer values , by obtan a set of value, two set of Struct with goset conpare value, owing to two struct property is different pointer, but the pointer value is equal, so goset.Contains(item) always false. Can have conpare Struct Pointer values?

The data struct is two way

  • package: `github.com/haproxytech/models
  • datastruct: models.Server

Phenomenon: goset.Contains() conpare the pointer address, not pointer value.

cylonchau avatar Mar 05 '23 16:03 cylonchau

Hi @cylonchau! Why won't you make the Set contain the actual value instead of a pointer to the value?

The Set object is designed to allow O(1) access, for both Contains() and Add(). It is implemented using a map, and all the values are stored as map keys. What you are asking for requires iterating over all the items, which kind of loses the main feature of the Set.

So I suggest you just store the values inside set set.Add(*item), and then do goset.Contains(*item)

amit7itz avatar Mar 06 '23 10:03 amit7itz

Hi @cylonchau! Why won't you make the Set contain the actual value instead of a pointer to the value?

The Set object is designed to allow O(1) access, for both Contains() and Add(). It is implemented using a map, and all the values are stored as map keys. What you are asking for requires iterating over all the items, which kind of loses the main feature of the Set.

So I suggest you just store the values inside set set.Add(*item), and then do goset.Contains(*item)

It's not this scenes, it is this scenes

the data struct is

type a struct {
   a1 int 
   b1 *int64
}

goset opreation

type_a := getAstruct()  // will get a values struct a { a1 = 1; b1= 2 }; but b1 pointer address = 0x0001

p = int64(1) // suppose the variable p address is 0x0002

type_b := a{a1: 1, b1:&p}

goset.Add(type_b)

goset.Contains(type_a) // false, because 0x0001 != 0x0002, the goset.Contains conpare pointer address, not pointer value

In the theory type_a == type_b , but attributes b1 is a pointer , the pointer address is diffrent value. So the goset.Contains always false.

If the goset element is a struct, and the struct attribute has pointer type, then goset.Contains always false. Because when we are comparing two element, for lookup with goset, the goset.Contains(attr), The address of pointer attribute of attr always no equal the address of pointer attribute of goset element

cylonchau avatar Mar 06 '23 13:03 cylonchau

Thanks for clarifying the issue @cylonchau.

I feel your pain, as although logically the two instances have the same values, they are not equal because of the pointer to a different memory address. The thing is, this is how pointers work, and there's not much to do about that...

If you take a look at goset's implementation, you can see it is implemented using a map, where the keys of the map are the items of the Set. goset doesn't really implement any comparison itself, it just adds/deletes keys from the map. And because of how structs are handled as map keys, pointer fields are considered by the memory address and not by the value they are pointing to.

This makes this issue not trivial to solve. It requires providing a way to define a custom hash function for that struct you are using and requires changing the Set implementation in a way that will make it heavier performance-wise.

Having said all that, I am interested to hear what are your suggestions for this pointer-fields problem. How do you imagine such a solution to look like?

amit7itz avatar Mar 08 '23 12:03 amit7itz

Thank you @amit7itz

I used other unpointer type resoved this problem, but pointer nature so. compare pointer value maybe is the goset point of improvement

cylonchau avatar Mar 08 '23 14:03 cylonchau