Why can't interface value be constant?

1,424 views
Skip to first unread message

T L

unread,
Aug 5, 2016, 2:21:43 PM8/5/16
to golang-nuts
For an interface value, its internal values will never change.
Are there any problems if golang supports constant interface values?

Ian Lance Taylor

unread,
Aug 5, 2016, 3:48:17 PM8/5/16
to T L, golang-nuts
On Fri, Aug 5, 2016 at 11:21 AM, T L <tapi...@gmail.com> wrote:
>
> For an interface value, its internal values will never change.
> Are there any problems if golang supports constant interface values?

Pedantically, in Go, constants are untyped by default. It doesn't
make sense to speak of an untyped interface value. I would describe
what you are asking for as an immutable variable. I've often thought
that immutable variables would be useful in Go, but since they have to
be initialized it's not that simple. For example, io.EOF is
initialized using a function call. That means that it can't actually
be in read-only memory, and of course it's possible to take it's
address. How do we prevent it from being changed, without introducing
an immutable qualifier into the type system? It's a complex problem
for which I have no solution. And the benefits of an immutable
variable aren't all that high.

Ian

T L

unread,
Aug 6, 2016, 3:53:26 AM8/6/16
to golang-nuts, tapi...@gmail.com
Is it possible to make an interface constant if its concrete value type is bool/number/string?

Dave Cheney

unread,
Aug 6, 2016, 3:58:52 AM8/6/16
to golang-nuts
It is not possible. Constants only exist at compile time.

atd...@gmail.com

unread,
Aug 6, 2016, 4:06:07 AM8/6/16
to golang-nuts, tapi...@gmail.com
Possibily, if you freeze the type of things that can be boxed by the interface. But what would it be useful for ?
That would just mean that an interface is constant. Not even that the value it wraps can't be changed (because with the current implementation, the values an interface wraps need to be addressable).

T L

unread,
Aug 6, 2016, 4:44:42 AM8/6/16
to golang-nuts, tapi...@gmail.com


On Saturday, August 6, 2016 at 4:06:07 PM UTC+8, atd...@gmail.com wrote:
Possibily, if you freeze the type of things that can be boxed by the interface. But what would it be useful for ?
That would just mean that an interface is constant. Not even that the value it wraps can't be changed (because with the current implementation, the values an interface wraps need to be addressable).

no, the value an interface wraps can't be addressed.

const bool/number/string interfaces make it is possible the exported error variables in standard lib become constant.
 

T L

unread,
Aug 6, 2016, 5:11:24 AM8/6/16
to golang-nuts, tapi...@gmail.com


On Saturday, August 6, 2016 at 4:06:07 PM UTC+8, atd...@gmail.com wrote:
Possibily, if you freeze the type of things that can be boxed by the interface. But what would it be useful for ?
That would just mean that an interface is constant. Not even that the value it wraps can't be changed (because with the current implementation, the values an interface wraps need to be addressable).

you mean a value should be addressable to let an interface wraps wrap it?
Not true, "_ = interface{}(1)" is valid in current implementation.
 

T L

unread,
Aug 6, 2016, 5:14:26 AM8/6/16
to golang-nuts


On Saturday, August 6, 2016 at 3:58:52 PM UTC+8, Dave Cheney wrote:
It is not possible. Constants only exist at compile time.

yes, but why constant interface values can't exist at compile time?
 

Dave Cheney

unread,
Aug 6, 2016, 5:19:08 AM8/6/16
to golang-nuts
Because an interface is a run time data structure, it cannot contain constants because they don't exist at run time.

T L

unread,
Aug 6, 2016, 5:30:22 AM8/6/16
to golang-nuts


On Saturday, August 6, 2016 at 5:19:08 PM UTC+8, Dave Cheney wrote:
Because an interface is a run time data structure, it cannot contain constants because they don't exist at run time.

I think an interface is not essential to be always a run time data structure. If compiler thinks it is constant, then it is constant.
 

Dave Cheney

unread,
Aug 6, 2016, 5:39:51 AM8/6/16
to golang-nuts
Interfaces don't describe data, they describe behaviour. If you don't want the behaviour to be changeable, use a concrete type.

atd...@gmail.com

unread,
Aug 6, 2016, 5:45:50 AM8/6/16
to golang-nuts, tapi...@gmail.com
No, I'm saying that the current implementation is two pointers.
The value is addressed by the second pointer. So you cannot really put a const in an interface. (thought experiment)

Of course, in the specific case of boxing a value type, that could work. If you accept that the *typ never changes throughout the program.

The question is, why a special case, what would you use it for? sync.Pools ?

If it's just for error variables to be constants, maybe it is not worth it. What problem does it solve ?

T L

unread,
Aug 6, 2016, 5:53:42 AM8/6/16
to golang-nuts, tapi...@gmail.com


On Saturday, August 6, 2016 at 5:45:50 PM UTC+8, atd...@gmail.com wrote:
No, I'm saying that the current implementation is two pointers.
The value is addressed by the second pointer. So you cannot really put a const in an interface. (thought experiment)

Of course, in the specific case of boxing a value type, that could work. If you accept that the *typ never changes throughout the program.

for constant intrfaces, the *typ property is not needed. Calling of their methods will confirmed at compile time.
 

The question is, why a special case, what would you use it for? sync.Pools ?

If it's just for error variables to be constants, maybe it is not worth it. What problem does it solve ?

for safety.
 

T L

unread,
Aug 6, 2016, 5:59:42 AM8/6/16
to golang-nuts


On Saturday, August 6, 2016 at 5:39:51 PM UTC+8, Dave Cheney wrote:
Interfaces don't describe data, they describe behaviour. If you don't want the behaviour to be changeable, use a concrete type.

There is the need to define many constant interface values of one special interface type, the concrete value types of these constant interface values may be different.
 

atd...@gmail.com

unread,
Aug 6, 2016, 6:04:00 AM8/6/16
to golang-nuts, tapi...@gmail.com


On Saturday, August 6, 2016 at 11:53:42 AM UTC+2, T L wrote:


On Saturday, August 6, 2016 at 5:45:50 PM UTC+8, atd...@gmail.com wrote:
No, I'm saying that the current implementation is two pointers.
The value is addressed by the second pointer. So you cannot really put a const in an interface. (thought experiment)

Of course, in the specific case of boxing a value type, that could work. If you accept that the *typ never changes throughout the program.

for constant intrfaces, the *typ property is not needed. Calling of their methods will confirmed at compile time.
 
You need it, the interface cannot be of any type, it would need to be initialized with a value of a given type for method dispatch.
The only thing is that the method dispatch would be fixed. (again a thought experiment :)

That's similar to sync.Value ( https://golang.org/pkg/sync/atomic/#Value)
 
 

The question is, why a special case, what would you use it for? sync.Pools ?

If it's just for error variables to be constants, maybe it is not worth it. What problem does it solve ?

for safety.

What is trhe safety issue? Do you have an example at hand? 

T L

unread,
Aug 6, 2016, 7:08:56 AM8/6/16
to golang-nuts, tapi...@gmail.com


On Saturday, August 6, 2016 at 6:04:00 PM UTC+8, atd...@gmail.com wrote:


On Saturday, August 6, 2016 at 11:53:42 AM UTC+2, T L wrote:


On Saturday, August 6, 2016 at 5:45:50 PM UTC+8, atd...@gmail.com wrote:
No, I'm saying that the current implementation is two pointers.
The value is addressed by the second pointer. So you cannot really put a const in an interface. (thought experiment)

Of course, in the specific case of boxing a value type, that could work. If you accept that the *typ never changes throughout the program.

for constant intrfaces, the *typ property is not needed. Calling of their methods will confirmed at compile time.
 
You need it, the interface cannot be of any type, it would need to be initialized with a value of a given type for method dispatch.
The only thing is that the method dispatch would be fixed. (again a thought experiment :) 

That's similar to sync.Value ( https://golang.org/pkg/sync/atomic/#Value)
 
 

The question is, why a special case, what would you use it for? sync.Pools ?

If it's just for error variables to be constants, maybe it is not worth it. What problem does it solve ?

for safety.

What is trhe safety issue? Do you have an example at hand? 

If you carelessly change the value of a global variable in std lib, some hard found bugs will be created.
 

atd...@gmail.com

unread,
Aug 6, 2016, 8:37:40 AM8/6/16
to golang-nuts, tapi...@gmail.com
If you carelessly do anything, you can introduce bugs.

Also note that it is fairly easy in Go to construct immutable "values".

The only thing we do not have is immutable value holders (let in other languages) which is a form of static single assignment at the language level.
The concept of variable is actually much more "functional" funnily enough, but I digress.

Just don't be careless and you should be fine. I have a hard time seeing why someone would want to assign a new value to a package level error variable.
Maybe you have a specific idea/example in mind?

atd...@gmail.com

unread,
Aug 6, 2016, 8:45:53 AM8/6/16
to golang-nuts, tapi...@gmail.com
On the other hand, I would like to see introduced some variant of slices with immutable backing arrays (it will allocate a lot though to modify a variable of that type) that would be comparable. That's a whole other topic however. slices are a much more delicate concept.

Ian Lance Taylor

unread,
Aug 6, 2016, 11:40:47 AM8/6/16
to T L, golang-nuts
On Sat, Aug 6, 2016 at 4:08 AM, T L <tapi...@gmail.com> wrote:
>
> If you carelessly change the value of a global variable in std lib, some
> hard found bugs will be created.

This is what you really want, and it is the reason I was talking about
immutable variables earlier.

In Go, a constant is created at compile time and always has that
value. You started this thread talking about the io.EOF variable.
The io.EOF variable is initialized with a function call. It is
written in the source code in io/io.go as

var EOF = errors.New("EOF")

In Go, it does not make sense to speak about a constant that is
initialized from a function call. Constants are set at compile time,
so when would that function call run?

If you look at the implementation of errors.New, you will see that it
returns a pointer. So even if you somehow decide that the result of
errors.New is a constant, what you have is a constant pointer. That
says nothing about the value to which the pointer points. Even if you
described the pointer as a Go const, the value to which the pointer
points could still be changed, so the overall meaning of the value can
change. So it's not enough to speak about a constant value. You have
to speak about a constant value that points to another constant value.
Of course, you can't take the address of a constant in Go--if you
could, you could change its value. So once again we are back to
talking about immutability.

It's easy to say the words "constant interface value." In the context
of a programming language, you need to think about what those words
really mean and how they would be implemented.

Ian
Reply all
Reply to author
Forward
0 new messages