简体   繁体   中英

Avoid same address for empty structs

In an attempt to have more useful enums in Go, I've tried using struct pointers as enum values. This works great if the struct has fields, but for the empty struct I sometimes get the same pointer multiple times, regardless of whether I use &Foo{} or new(Foo) .

Is there any way I can force the pointers to be different?

This is what I'm trying to do ( try it online ):

package main

type Foo struct{}

var FooValues = struct {
    Alpha   *Foo
    Bravo   *Foo
    Charlie *Foo
}{
    Alpha:   &Foo{}, // These pointers should all be different
    Bravo:   &Foo{}, // But sometimes
    Charlie: &Foo{}, // They are not
}

func main() {
    if FooValues.Alpha == FooValues.Charlie {
        panic("enum values are the same!")
    }
}

Is there any way I can force the pointers to be different?

No. Any implementation is allowed to use the same address. You must redesign.

From the Go language specification :

Pointers to distinct zero-size variables may or may not be equal.

This seems to do it:

package main

type foo struct{}

func newFoo() *foo {
   return new(foo)
}

type fooValues struct { alpha, bravo, charlie *foo }

func newFooValues() fooValues {
   return fooValues{
      newFoo(), newFoo(), newFoo(),
   }
}

func main() {
   f := newFooValues()
   if f.alpha == f.charlie {
      panic("enum values are the same!")
   }
}

As mentioned, pointer comparison for zero-sized types is not reliable in this way.

Replace

type Foo struct{}

with

type Foo struct{int}

Now your code works. The added cost is ~1 word of memory per enum that you allocate, which should be negligible in most cases.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM