2009/12/3 Russ Cox <
r...@golang.org>:
> it does exclude a useful case or two, like
>
> type Point { x, y int }
"a useful case or two" includes *all* structs that are used by value
unless you want to export all their fields.
i agree that it's useful to be able to prevent the
unmoderated copying of structs that have been returned
by reference, but i still think the rule in this case is too strong,
and that a weaker rule can suffice.
given the useful rule about generating an
automatic reference to a value-structure when
it's used by reference, surely this would be an good thing?
> but in general it works well and its behavior follows
> from a very simple rule.
it works well because most exported structs are
used by reference.
>> essentially: if you export any transactions involving the
>> struct by value, then all copying becomes fair game,
>> unexported fields or not.
>
> it seems like a mistake to change the access rules
> depending on whether a particular kind of function
> happens to have been written. what if it's dead code
> and gets removed in a cleanup?
i wasn't talking about *all* functions, just exported functions.
i agree that it does sound a bit unusual, but think
of it this way: if your package exports a function that returns a structure
by value, then you're inviting the structure to be used by value.
if you exported such a function by mistake, then at the worst
you might have some code exploiting something similarly to
your os.Open() case. but such exploit code would have to have been
written deliberately; it's easy to automatically check what
the access rules are; and it's highly unlikely that such functions
will be written anyway - in general if a structure is used by-reference,
then it's passed everywhere by reference.
can you find any instance in the current code where there's a by-value
usage that would cause the rule to apply innappropriately?
even if there was some dubious "dead code", when it's cleaned up, any
"exploit" code
immediately fails to compile.
as an alternative, it would be possible to add a modifier to
a type declaration to make the type "reference only", but
i think it's unnecessary, given how things can be determined from
normal usage.
in return, i think the "reference-only" rules should be much
more strictly applied. for a reference-only struct type T with unexported
fields, i think most of the usages in eadfrith's post should be illegal.
in particular, new(T), make([]T), make(chan T), local struct copying, etc
should all be illegal.
then we can statically assertain that all instances of *T have been
created by its original package. currently you can do new(os.File).Close()
which i don't think is correct.