FAQ
I recently ran into an issue with the Go type system related function
parameter type assignment.

Consider the following setup:

type A interface {
     X() int
}


type B interface {
     X() int
     Y() int
}


func FuncA(a A) {
     fmt.Printf("%T A: %d\n", a, a.X())
}
(Full Example <http://play.golang.org/p/ns32SA5U3q>)

Using these types, one can easily create a struct that implements B and
then pass it into FuncA. In particular, note that *any* value of type B can
be passed to FuncA, since any value of type B is also of type A.
Based on this, one might assume that FuncA might be assignable to a
variable of type func(B) but according to Golang's type assignment rules
<http://golang.org/ref/spec#Assignability>, this is illegal.

This case becomes even more contrived, when B is made the same type as A
<http://play.golang.org/p/P4dimkSGZT>.

This case also extends to return types as well, but in reverse (func() B
can be safely used in place of func() A).

In Golang, the sort of type equivalence between interfaces is very
intuitive, and lends itself to a sort of "can be used in place of"
relationship between interfaces and other types. However, this is not the
case for functions, since a func(A) can be safely used in place of a
func(B) (although the type system disallows this).

Why was this type assignment of functions disallowed? Was it simply left
out because it was difficult to implement or not useful? Did it conflict
with other goals of the type system? Is this "can be used in place of" way
of thinking about types not what the type system was laid out to represent?

In general, I have found several blog posts and documents describing the
behavior and syntax of the golang type system (example
<http://jordanorelli.com/post/42369331748/function-types-in-go-golang>,
example <http://blog.golang.org/gos-declaration-syntax>), but have been
unable to find any design documents as to why these design choices were
made this way. If such a document existed somewhere, I would very much like
to read it.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Ian Lance Taylor at Aug 12, 2014 at 12:24 am

    On Mon, Aug 11, 2014 at 4:57 PM, Zeal Jagannatha wrote:

    Using these types, one can easily create a struct that implements B and then
    pass it into FuncA. In particular, note that any value of type B can be
    passed to FuncA, since any value of type B is also of type A.
    Yes, because Go permits an implicit conversion from any type to an
    interface type which that implements. This is one of the few implicit
    type conversions in Go.

    Based on this, one might assume that FuncA might be assignable to a variable
    of type func(B) but according to Golang's type assignment rules, this is
    illegal.
    Yes, you might assume that, but, as you know, you would be wrong. An
    implicit conversion between types is still a conversion. An implicit
    conversion from A to B is not an implicit conversion from a type based
    on A to a type bsaed on B in the same way.

    In Golang, the sort of type equivalence between interfaces is very
    intuitive, and lends itself to a sort of "can be used in place of"
    relationship between interfaces and other types. However, this is not the
    case for functions, since a func(A) can be safely used in place of a func(B)
    (although the type system disallows this).
    It's not the case for any derived type, including function types.

    Why was this type assignment of functions disallowed? Was it simply left out
    because it was difficult to implement or not useful? Did it conflict with
    other goals of the type system? Is this "can be used in place of" way of
    thinking about types not what the type system was laid out to represent?
    One reason it's left out is orthogonality. If implicit conversion
    from B to A permits implicit conversion from func(B) to func(A), then
    why not permit implicit conversion from *B to *A? Or []B to []A? But
    at that point the implicit conversion is costly at runtime, because A
    and B do not have identical representations.

    Another reason it's left out is because, since A and B do not look the
    same at runtime, the conversion from func(B) to func(A) actually
    requires inserting a helper function.
         var f func(B) = funcA
    must be translated as something like
         var f = func(b B) { funcA(b) }
    Without that helper function there is no place to implement the
    conversion from B to A. But an implicit conversion that requires
    creating a new closure seems overly complex.

    Ian

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedAug 11, '14 at 11:57p
activeAug 12, '14 at 12:24a
posts2
users2
websitegolang.org

People

Translate

site design / logo © 2021 Grokbase