70

Why can't I create constant struct?

const FEED_TO_INSERT = quzx.RssFeed{ 0,
                    "",
                    "desc",
                    "www.some-site.com",
                    "upd_url",
                    "img_title",
                    "img_url",
                    0,
                    0,
                    0,
                    0,
                    0,
                    100,
                    "alt_name",
                    1,
                    1,
                    1,
                    "test",
                    100,
                    100,
                    0 }

.\rss_test.go:32: const initializer quzx.RssFeed literal is not a constant

mklement0
  • 382,024
  • 64
  • 607
  • 775
ceth
  • 44,198
  • 62
  • 180
  • 289
  • 1
    Can you add the link to the answered question? It would be good to link back to the original question for duplicating. – Zhenhua Nov 14 '17 at 23:30
  • 2
    Flagging to reopen. Asking if you can make a constant struct is different to asking about an array, even if the *answers* are similar. – Duncan Jones May 02 '19 at 11:15
  • Constant structs have the potential implementation issue that user may try to assign to a constant field, which is possibly the reason why they didn't implement this to start with. – SOFe May 17 '23 at 03:43

5 Answers5

102

Because Go does not support struct constants (emphasis mine)

There are boolean constants, rune constants, integer constants, floating-point constants, complex constants, and string constants. Rune, integer, floating-point, and complex constants are collectively called numeric constants.

Read more here: https://golang.org/ref/spec#Constants

mkopriva
  • 35,176
  • 4
  • 57
  • 71
27

A good workaround is to wrap it in a function.

func FEED_TO_INSERT() quzx.RssFeed {
    return quzx.RssFeed{ 0,
                    "",
                    "desc",
                    "www.some-site.com",
                    "upd_url",
                    "img_title",
                    "img_url",
                    0,
                    0,
                    0,
                    0,
                    0,
                    100,
                    "alt_name",
                    1,
                    1,
                    1,
                    "test",
                    100,
                    100,
                    0 }
}

Note: Make sure that the function is always returning a new object(or copy).

Ihor
  • 461
  • 4
  • 8
  • 3
    You emulate something constant, which can not change and should be identical to itself, by "always returning a new object". Sounds strange. – ceving Jan 27 '23 at 15:33
21

You should declare it as a var.

Go allows you to declare and initialize global variables at module scope.

Go does not have any concept of immutability. 'const' is not meant as a way to prevent variables from mutating or anything like that.

user10753492
  • 720
  • 4
  • 8
  • 5
    This is true (`const` in Go is closer to `#define` in C than to `readonly` in C#), but doesn't really explain why there can't be struct-like `const` values. They were probably excluded (along with array-like and map-like values) to simplify the compiler design. – kbolino Sep 19 '21 at 18:38
0

You could declare your struct fields as private and then create getter methods.

type ImmutableType struct {
  immutableField string
}

func (p ImmutableType) GetImmutableField() string {
  return p.immutableField
}

If you do this, the field itself will be inaccessible outside the module and will become sort of immutable.

However,

  • this can only be done on the struct level, not when declaring a variable
  • if you want to instantiate your struct outside of the module, you'll have to also create a constructor, which becomes kind of a mess since constructors are not really a commonly used practice in Go.

In order to "force" the use of your constructor, you might also declare your struct itself private, so it cannot be created as a composite literal without the private fields.

type immutableType struct {
  immutableField string
}

func (p immutableType) GetImmutableField() string {
  return p.immutableField
}

func CreateImmutableType(immutableField string) immutableType {
  return immutableType{
    immutableField: immutableField,
  }
}

TL;DR Go doesn't have immutability as a core concept, so implementing it requires a bunch of boilerplate.

Igor Gunin
  • 173
  • 7
0

As was said, Go does not support constant struct variables. This has a reason, compiler cannot ensure immutability of any struct (e.g. containing a pointer). Solution is rather simple: just use normal variable:

type Person struct {
    age int
}

var Luke = Person{10}

You can also use anonymous struct:

var Andrew = struct {
    age int
}{
    age: 13,
}

When you create this as a global variable, treat it as that - with care. The other recommendation is to use a function to return always a copy and that is the other extreme.

lzap
  • 16,417
  • 12
  • 71
  • 108