86

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

3
  • 1
    Can you add the link to the answered question? It would be good to link back to the original question for duplicating. Commented Nov 14, 2017 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. Commented May 2, 2019 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. Commented May 17, 2023 at 3:43

6 Answers 6

110

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

Sign up to request clarification or add additional context in comments.

1 Comment

Sad. This is a handy language feature.
31

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).

2 Comments

You emulate something constant, which can not change and should be identical to itself, by "always returning a new object". Sounds strange.
This works functionally, but may have performance impact on memory & computation, unless go caches the function result. I wonder if go does do that compiler optimization.
23

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.

1 Comment

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.
1

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.

Comments

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.

Comments

0

There is a possible implementation using type alias. As in mkopriva answer, only some intrinsic types can be constants. However, you can define a new type on top of those and write getters for your constant values.

package main

import "fmt"

type Config bool

func (_ Config) Prop() int {
    return -1
}

const DefaultConfig Config = false

func main() {
    fmt.Println(DefaultConfig.Prop())

    // This will not work
    // variable := Config(true)
    // DefaultConfig = variable
}

At the time I'm writing this, the Prop() function meets the requirements for inlining, so you may expect no overhead coming from the function call.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.