FAQ
I was going through the Go tour, and I hit 68 (Exercise: Equivalent
Binary Trees) and decided to have a go (heh, puns) by myself without
going any further into the slides. I defined a Tree interface, made an
implementation equivalent to the one on slide 68 (called StructTree in
my code), wrote a Compare function and created a test harness. However,
I can't get the thing to work. :(

Ultimately I think the problems stem from me misunderstanding the
nuances of pointers to interfaces vs. pointers to implementations of
interfaces. I have attached a .tar.gz of my source with comments in
explaining what I think is happening and why I'm so confused.

The error I am getting at the moment is
`--> go test
# tree
./compare_test.go:25: cannot use t1 (type *StructTree) as type *Tree in
function argument:
*Tree is pointer to interface, not interface
./compare_test.go:25: cannot use t2 (type *StructTree) as type *Tree in
function argument:
*Tree is pointer to interface, not interface
FAIL tree [build failed]
which I believe is because Compare expects *Trees, which are not
pointers to structs implementing trees as I expect, but pointers to the
actual interface. So basically I am confused about the difference in
syntax between a pointer to a struct implementing an interface and a
pointer to an actual interface.

No spoilers about my code's functionality or other issues yet please,
once I've got this fixed I'd like to try fixing anything else by
myself. :) Thanks in advance.

--

Search Discussions

  • Kyle Lemons at Dec 20, 2012 at 12:34 am
    First: Never* use pointers to interfaces.

    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets
    <http://code.google.com/p/go-wiki/wiki/MethodSets>wiki entry, to
    better understand what values can be stored in an interface
    and the struct pointer/value differences.
    2) Read up on their implementation <http://research.swtch.com/godata>, if
    you are the sort who understands better by knowing what's going on behind
    the curtain

    * By the time you need to break this rule, you'll understand why the rule
    says "never."

    HTH,

    On Wed, Dec 19, 2012 at 4:45 PM, John Preston wrote:

    I was going through the Go tour, and I hit 68 (Exercise: Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself without
    going any further into the slides. I defined a Tree interface, made an
    implementation equivalent to the one on slide 68 (called StructTree in
    my code), wrote a Compare function and created a test harness. However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding the
    nuances of pointers to interfaces vs. pointers to implementations of
    interfaces. I have attached a .tar.gz of my source with comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are not
    pointers to structs implementing trees as I expect, but pointers to the
    actual interface. So basically I am confused about the difference in
    syntax between a pointer to a struct implementing an interface and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet please,
    once I've got this fixed I'd like to try fixing anything else by
    myself. :) Thanks in advance.

    --

    --
  • John Preston at Dec 20, 2012 at 10:49 am
    That's helped a lot, thanks Kyle, but I'm still having problems. I have
    updated my code based upon my revised understanding (which is that Tree
    is an interface and so SomeFunc(t Tree) will accept structs implementing
    Tree and pointers to those structs) but now I am getting these errors:

    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    FAIL tree [build failed]

    I am passing *StructTrees to a function that accepts Trees, and
    StructTree implements Tree methods such as 'Left() Tree' using methods
    with signatures like '(StructTree) Left() *StructTree'. My understanding
    is that this gives StructTree a valid implementation of Tree because it
    returns a pointer to a struct which implements Tree, namely a
    StructTree. However, the error I'm getting seem to imply that I cannot
    use a *StructTree where I want a Tree, even though *StructTree would
    receive the same methods.

    I take it this is because of the recursive definition of the Tree-ness
    of StructTree (due to it returning *StructTrees instead of Trees), but
    if my methods have to return Trees then my interface and my
    implementation are not decoupled. :S
    On Wed, 2012-12-19 at 19:34 -0500, Kyle Lemons wrote:
    First: Never* use pointers to interfaces.

    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets
    <http://code.google.com/p/go-wiki/wiki/MethodSets>wiki entry, to
    better understand what values can be stored in an interface
    and the struct pointer/value differences.
    2) Read up on their implementation <http://research.swtch.com/godata>, if
    you are the sort who understands better by knowing what's going on behind
    the curtain

    * By the time you need to break this rule, you'll understand why the rule
    says "never."

    HTH,

    On Wed, Dec 19, 2012 at 4:45 PM, John Preston wrote:

    I was going through the Go tour, and I hit 68 (Exercise: Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself without
    going any further into the slides. I defined a Tree interface, made an
    implementation equivalent to the one on slide 68 (called StructTree in
    my code), wrote a Compare function and created a test harness. However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding the
    nuances of pointers to interfaces vs. pointers to implementations of
    interfaces. I have attached a .tar.gz of my source with comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are not
    pointers to structs implementing trees as I expect, but pointers to the
    actual interface. So basically I am confused about the difference in
    syntax between a pointer to a struct implementing an interface and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet please,
    once I've got this fixed I'd like to try fixing anything else by
    myself. :) Thanks in advance.

    --

    First: Never* use pointers to interfaces.


    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets wiki entry, to better understand what values
    can be stored in an interface and the struct pointer/value
    differences.
    2) Read up on their implementation, if you are the sort who
    understands better by knowing what's going on behind the curtain


    * By the time you need to break this rule, you'll understand why the
    rule says "never."


    HTH,


    On Wed, Dec 19, 2012 at 4:45 PM, John Preston wrote:
    I was going through the Go tour, and I hit 68 (Exercise:
    Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself
    without
    going any further into the slides. I defined a Tree interface,
    made an
    implementation equivalent to the one on slide 68 (called
    StructTree in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding
    the
    nuances of pointers to interfaces vs. pointers to
    implementations of
    interfaces. I have attached a .tar.gz of my source with
    comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are
    not
    pointers to structs implementing trees as I expect, but
    pointers to the
    actual interface. So basically I am confused about the
    difference in
    syntax between a pointer to a struct implementing an interface
    and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet
    please,
    once I've got this fixed I'd like to try fixing anything else
    by
    myself. :) Thanks in advance.

    --


    --
  • Volker Dobler at Dec 20, 2012 at 12:12 pm

    Am Donnerstag, 20. Dezember 2012 11:49:50 UTC+1 schrieb John Preston:

    That's helped a lot, thanks Kyle, but I'm still having problems. I have
    updated my code based upon my revised understanding (which is that Tree
    is an interface and so SomeFunc(t Tree) will accept structs implementing
    Tree and pointers to those structs)
    That is correct.

    but now I am getting these errors:
    [snip]
    I am passing *StructTrees to a function that accepts Trees, and
    StructTree implements Tree methods such as 'Left() Tree' using methods
    with signatures like '(StructTree) Left() *StructTree'. My understanding
    is that this gives StructTree a valid implementation of Tree because it
    returns a pointer to a struct which implements Tree, namely a
    StructTree.
    That one is wrong. The Left method in interface Tree returns
    the type Tree but StructTree's Left returns *StrcutTree
    which simply isn't Tree, it "just" implements Tree. Thus StructTree does
    not implement Tree.

    However, the error I'm getting seem to imply that I cannot
    use a *StructTree where I want a Tree, even though *StructTree would
    receive the same methods.
    Almost: A *StructTree does not have the same methods as its Left
    method returns a *StructTree while while Tree requires a Tree.
    Go is really strict in typing: Tree and *StructTree are different types.

    I take it this is because of the recursive definition of the Tree-ness
    of StructTree (due to it returning *StructTrees instead of Trees), but
    if my methods have to return Trees then my interface and my
    implementation are not decoupled. :S
    What would be the benefit of this decoupling? Who would profit?
    Why not have *StructTree's Left method return a Tree which you
    can typecast to *StructTree where needed (e.g. in ContainsAcc).

    Volker

    --
  • Nate Finch at Dec 20, 2012 at 12:14 pm
    Yeah, unfortunately, the struct has to implement the interface exactly. It
    can't have methods that return concrete types where the interface expects
    it to return interfaces, even if the concrete types implement those
    interfaces. That type of polymorphism doesn't work. Similarly, you can't
    pass an array or slice of StructTree into a method expecting an array or
    slice of Tree.

    That kind of one-step-away indirection just doesn't work. However, in your
    program, the interface is largely superfluous anyway, so you can probably
    just drop it entirely.... or you can have structtree's Left method return a
    Tree.

    I'm sure there's a specific reason in the compiler why that doesn't work
    (size of the structure in memory is the usual answer), but it's just the
    way it is.
    On Thursday, December 20, 2012 5:49:50 AM UTC-5, John Preston wrote:

    That's helped a lot, thanks Kyle, but I'm still having problems. I have
    updated my code based upon my revised understanding (which is that Tree
    is an interface and so SomeFunc(t Tree) will accept structs implementing
    Tree and pointers to those structs) but now I am getting these errors:

    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    FAIL tree [build failed]

    I am passing *StructTrees to a function that accepts Trees, and
    StructTree implements Tree methods such as 'Left() Tree' using methods
    with signatures like '(StructTree) Left() *StructTree'. My understanding
    is that this gives StructTree a valid implementation of Tree because it
    returns a pointer to a struct which implements Tree, namely a
    StructTree. However, the error I'm getting seem to imply that I cannot
    use a *StructTree where I want a Tree, even though *StructTree would
    receive the same methods.

    I take it this is because of the recursive definition of the Tree-ness
    of StructTree (due to it returning *StructTrees instead of Trees), but
    if my methods have to return Trees then my interface and my
    implementation are not decoupled. :S
    On Wed, 2012-12-19 at 19:34 -0500, Kyle Lemons wrote:
    First: Never* use pointers to interfaces.

    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets
    <http://code.google.com/p/go-wiki/wiki/MethodSets>wiki entry, to
    better understand what values can be stored in an interface
    and the struct pointer/value differences.
    2) Read up on their implementation <http://research.swtch.com/godata>, if
    you are the sort who understands better by knowing what's going on behind
    the curtain

    * By the time you need to break this rule, you'll understand why the rule
    says "never."

    HTH,

    On Wed, Dec 19, 2012 at 4:45 PM, John Preston wrote:

    I was going through the Go tour, and I hit 68 (Exercise: Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself without
    going any further into the slides. I defined a Tree interface, made an
    implementation equivalent to the one on slide 68 (called StructTree in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding the
    nuances of pointers to interfaces vs. pointers to implementations of
    interfaces. I have attached a .tar.gz of my source with comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type *Tree
    in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type *Tree
    in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are not
    pointers to structs implementing trees as I expect, but pointers to
    the
    actual interface. So basically I am confused about the difference in
    syntax between a pointer to a struct implementing an interface and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet please,
    once I've got this fixed I'd like to try fixing anything else by
    myself. :) Thanks in advance.

    --

    First: Never* use pointers to interfaces.


    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets wiki entry, to better understand what values
    can be stored in an interface and the struct pointer/value
    differences.
    2) Read up on their implementation, if you are the sort who
    understands better by knowing what's going on behind the curtain


    * By the time you need to break this rule, you'll understand why the
    rule says "never."


    HTH,


    On Wed, Dec 19, 2012 at 4:45 PM, John Preston <gizm...@gmail.com<javascript:>>
    wrote:
    I was going through the Go tour, and I hit 68 (Exercise:
    Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself
    without
    going any further into the slides. I defined a Tree interface,
    made an
    implementation equivalent to the one on slide 68 (called
    StructTree in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding
    the
    nuances of pointers to interfaces vs. pointers to
    implementations of
    interfaces. I have attached a .tar.gz of my source with
    comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are
    not
    pointers to structs implementing trees as I expect, but
    pointers to the
    actual interface. So basically I am confused about the
    difference in
    syntax between a pointer to a struct implementing an interface
    and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet
    please,
    once I've got this fixed I'd like to try fixing anything else
    by
    myself. :) Thanks in advance.

    --


    --
  • Gizmoguy1 at Dec 20, 2012 at 1:23 pm
    Hmm this is quite upsetting, I'm used to the polymorphism and generics in
    Java. Is this kind of think likely to be an issue in any Go programming? Is
    this because I'm not going about this in the Go way?
    On Thursday, 20 December 2012 12:14:51 UTC, Nate Finch wrote:

    Yeah, unfortunately, the struct has to implement the interface exactly.
    It can't have methods that return concrete types where the interface
    expects it to return interfaces, even if the concrete types implement those
    interfaces. That type of polymorphism doesn't work. Similarly, you can't
    pass an array or slice of StructTree into a method expecting an array or
    slice of Tree.

    That kind of one-step-away indirection just doesn't work. However, in your
    program, the interface is largely superfluous anyway, so you can probably
    just drop it entirely.... or you can have structtree's Left method return a
    Tree.

    I'm sure there's a specific reason in the compiler why that doesn't work
    (size of the structure in memory is the usual answer), but it's just the
    way it is.
    On Thursday, December 20, 2012 5:49:50 AM UTC-5, John Preston wrote:

    That's helped a lot, thanks Kyle, but I'm still having problems. I have
    updated my code based upon my revised understanding (which is that Tree
    is an interface and so SomeFunc(t Tree) will accept structs implementing
    Tree and pointers to those structs) but now I am getting these errors:

    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    FAIL tree [build failed]

    I am passing *StructTrees to a function that accepts Trees, and
    StructTree implements Tree methods such as 'Left() Tree' using methods
    with signatures like '(StructTree) Left() *StructTree'. My understanding
    is that this gives StructTree a valid implementation of Tree because it
    returns a pointer to a struct which implements Tree, namely a
    StructTree. However, the error I'm getting seem to imply that I cannot
    use a *StructTree where I want a Tree, even though *StructTree would
    receive the same methods.

    I take it this is because of the recursive definition of the Tree-ness
    of StructTree (due to it returning *StructTrees instead of Trees), but
    if my methods have to return Trees then my interface and my
    implementation are not decoupled. :S
    On Wed, 2012-12-19 at 19:34 -0500, Kyle Lemons wrote:
    First: Never* use pointers to interfaces.

    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets
    <http://code.google.com/p/go-wiki/wiki/MethodSets>wiki entry, to
    better understand what values can be stored in an interface
    and the struct pointer/value differences.
    2) Read up on their implementation <http://research.swtch.com/godata>, if
    you are the sort who understands better by knowing what's going on behind
    the curtain

    * By the time you need to break this rule, you'll understand why the rule
    says "never."

    HTH,


    On Wed, Dec 19, 2012 at 4:45 PM, John Preston <gizm...@gmail.com>
    wrote:
    I was going through the Go tour, and I hit 68 (Exercise: Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself without
    going any further into the slides. I defined a Tree interface, made
    an
    implementation equivalent to the one on slide 68 (called StructTree
    in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding the
    nuances of pointers to interfaces vs. pointers to implementations of
    interfaces. I have attached a .tar.gz of my source with comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type *Tree
    in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type *Tree
    in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are not
    pointers to structs implementing trees as I expect, but pointers to
    the
    actual interface. So basically I am confused about the difference in
    syntax between a pointer to a struct implementing an interface and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet please,
    once I've got this fixed I'd like to try fixing anything else by
    myself. :) Thanks in advance.

    --

    First: Never* use pointers to interfaces.


    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets wiki entry, to better understand what values
    can be stored in an interface and the struct pointer/value
    differences.
    2) Read up on their implementation, if you are the sort who
    understands better by knowing what's going on behind the curtain


    * By the time you need to break this rule, you'll understand why the
    rule says "never."


    HTH,


    On Wed, Dec 19, 2012 at 4:45 PM, John Preston <gizm...@gmail.com>
    wrote:
    I was going through the Go tour, and I hit 68 (Exercise:
    Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself
    without
    going any further into the slides. I defined a Tree interface,
    made an
    implementation equivalent to the one on slide 68 (called
    StructTree in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding
    the
    nuances of pointers to interfaces vs. pointers to
    implementations of
    interfaces. I have attached a .tar.gz of my source with
    comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are
    not
    pointers to structs implementing trees as I expect, but
    pointers to the
    actual interface. So basically I am confused about the
    difference in
    syntax between a pointer to a struct implementing an interface
    and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet
    please,
    once I've got this fixed I'd like to try fixing anything else
    by
    myself. :) Thanks in advance.

    --


    --
  • Volker Dobler at Dec 20, 2012 at 2:11 pm

    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and generics in
    Java.

    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go programming?

    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface

    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.

    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?

    Volker

    --
  • John Preston at Dec 20, 2012 at 2:22 pm
    I could change the return type of Left() and Right() to be Tree, but I
    thought one of the reasons Go does interfaces the way it does is so that
    I can implement them without directly acknowledging their existence.
    On Thu, 2012-12-20 at 06:11 -0800, Volker Dobler wrote:

    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and generics in
    Java.

    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go programming?

    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface

    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.

    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?

    Volker



    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb
    gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and
    generics in Java.


    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go
    programming?


    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface


    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.


    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?


    Volker



    --

    --
  • Nate Finch at Dec 20, 2012 at 3:48 pm
    I think hanging left and right to return a Tree is the right fix. Like I
    said before, you don't technically need any interfaces in this
    implementation, but I can see why you would want to implement the function
    to compare the trees to take an interface.

    Note that in the tour example you're working on, Tree is a struct, and they
    don't use interfaces at all.
    On Thursday, December 20, 2012 9:22:31 AM UTC-5, John Preston wrote:

    I could change the return type of Left() and Right() to be Tree, but I
    thought one of the reasons Go does interfaces the way it does is so that
    I can implement them without directly acknowledging their existence.
    On Thu, 2012-12-20 at 06:11 -0800, Volker Dobler wrote:

    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb
    gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and generics
    in
    Java.

    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go programming?

    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface

    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.

    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?

    Volker



    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb
    gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and
    generics in Java.


    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go
    programming?


    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface


    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.


    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?


    Volker



    --
    --
  • Nate Finch at Dec 20, 2012 at 3:53 pm
    hanging -> changing

    --
  • Chris dollin at Dec 20, 2012 at 4:10 pm

    On 20 December 2012 14:22, John Preston wrote:
    I could change the return type of Left() and Right() to be Tree, but I
    thought one of the reasons Go does interfaces the way it does is so that
    I can implement them without directly acknowledging their existence.
    You can do that, but then the interface methods must use the same
    argument and result types as the implementation does.

    They have to match, either because a later implementation
    uses the same types that the interface methods do or because
    a later interface uses the same types some concrete type does
    for its methods.

    Chris

    --
    Chris "allusive" Dollin

    --
  • Sabinevolkerlukas at Dec 20, 2012 at 4:10 pm
    StructTree still doesn't need to explicitly declare that it implements Tree.
    Just because there _can_ be an interface I which is implemented by a type
    T which doesn't know it does (and that I exists) doesn't mean that a
    type must ignore that interface. What is wrong with SrtructTree knowing
    that it is a Tree?
    On Thursday, December 20, 2012 3:22:31 PM UTC+1, John Preston wrote:

    I could change the return type of Left() and Right() to be Tree, but I
    thought one of the reasons Go does interfaces the way it does is so that
    I can implement them without directly acknowledging their existence.
    On Thu, 2012-12-20 at 06:11 -0800, Volker Dobler wrote:

    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb
    gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and generics
    in
    Java.

    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go programming?

    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface

    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.

    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?

    Volker



    Am Donnerstag, 20. Dezember 2012 14:23:39 UTC+1 schrieb
    gizm...@gmail.com:
    Hmm this is quite upsetting, I'm used to the polymorphism and
    generics in Java.


    Yes, this typically bugs someone with a strong Java background

    Is this kind of think likely to be an issue in any Go
    programming?


    Yes and no. No, it is _much_ less likely to be an issue than your Java
    background
    might suggest. But Yes, sometimes it would be nice to assign a
    []SomethingTypeImplementingThisInterface to a []ThisInterface


    Is this because I'm not going about this in the Go way?
    Maybe. In Go interface tend to be much more useful than in Java.
    Don't try to write Java programs in Go.


    As neither left nor right in StructTree are exported: Why not return a
    Tree in the Left and Right methods?


    Volker



    --
    --
  • Kyle Lemons at Dec 20, 2012 at 5:12 pm
    In Go, it is difficult to make an interface that behaves like a container
    type. Interfaces are intended to be behavioral, not architectural.

    To create a somewhat contrived example, a tree interface might be

    type Traversal int
    const (
    InOrder Traversal = iota
    PreOrder
    PostOrder
    DepthFirst
    BreadthFirst
    )
    type Tree interface {
    Traverse(order Traversal, each func(v Type))
    }

    This specifies the behavior that the tree should have--that is, it should
    be able to be traversed in a number of ways. Specifying that it must have
    a left and a right method is architectural in that it imposes stricture on
    how the tree is implemented and asks that behavior be implemented on top of
    the interface, not behind it.

    On Thu, Dec 20, 2012 at 8:23 AM, wrote:

    Hmm this is quite upsetting, I'm used to the polymorphism and generics in
    Java. Is this kind of think likely to be an issue in any Go programming? Is
    this because I'm not going about this in the Go way?

    On Thursday, 20 December 2012 12:14:51 UTC, Nate Finch wrote:

    Yeah, unfortunately, the struct has to implement the interface exactly.
    It can't have methods that return concrete types where the interface
    expects it to return interfaces, even if the concrete types implement those
    interfaces. That type of polymorphism doesn't work. Similarly, you can't
    pass an array or slice of StructTree into a method expecting an array or
    slice of Tree.

    That kind of one-step-away indirection just doesn't work. However, in
    your program, the interface is largely superfluous anyway, so you can
    probably just drop it entirely.... or you can have structtree's Left method
    return a Tree.

    I'm sure there's a specific reason in the compiler why that doesn't work
    (size of the structure in memory is the usual answer), but it's just the
    way it is.
    On Thursday, December 20, 2012 5:49:50 AM UTC-5, John Preston wrote:

    That's helped a lot, thanks Kyle, but I'm still having problems. I have
    updated my code based upon my revised understanding (which is that Tree
    is an interface and so SomeFunc(t Tree) will accept structs implementing
    Tree and pointers to those structs) but now I am getting these errors:

    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type Tree in
    function argument:
    *StructTree does not implement Tree (wrong type for Left method)
    have Left() *StructTree
    want Left() Tree
    FAIL tree [build failed]

    I am passing *StructTrees to a function that accepts Trees, and
    StructTree implements Tree methods such as 'Left() Tree' using methods
    with signatures like '(StructTree) Left() *StructTree'. My understanding
    is that this gives StructTree a valid implementation of Tree because it
    returns a pointer to a struct which implements Tree, namely a
    StructTree. However, the error I'm getting seem to imply that I cannot
    use a *StructTree where I want a Tree, even though *StructTree would
    receive the same methods.

    I take it this is because of the recursive definition of the Tree-ness
    of StructTree (due to it returning *StructTrees instead of Trees), but
    if my methods have to return Trees then my interface and my
    implementation are not decoupled. :S
    On Wed, 2012-12-19 at 19:34 -0500, Kyle Lemons wrote:
    First: Never* use pointers to interfaces.

    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets
    <http://code.google.com/p/go-**wiki/wiki/MethodSets<http://code.google.com/p/go-wiki/wiki/MethodSets>>wiki entry, to
    better understand what values can be stored in an interface
    and the struct pointer/value differences.
    2) Read up on their implementation <http://research.swtch.com/**godata<http://research.swtch.com/godata>>, if
    you are the sort who understands better by knowing what's going on behind
    the curtain

    * By the time you need to break this rule, you'll understand why the rule
    says "never."

    HTH,


    On Wed, Dec 19, 2012 at 4:45 PM, John Preston <gizm...@gmail.com>
    wrote:
    I was going through the Go tour, and I hit 68 (Exercise: Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself without
    going any further into the slides. I defined a Tree interface, made
    an
    implementation equivalent to the one on slide 68 (called StructTree
    in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding the
    nuances of pointers to interfaces vs. pointers to implementations of
    interfaces. I have attached a .tar.gz of my source with comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type *Tree
    in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type *Tree
    in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are not
    pointers to structs implementing trees as I expect, but pointers to
    the
    actual interface. So basically I am confused about the difference in
    syntax between a pointer to a struct implementing an interface and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet
    please,
    once I've got this fixed I'd like to try fixing anything else by
    myself. :) Thanks in advance.

    --

    First: Never* use pointers to interfaces.


    I'd suggest two things to get a better feel for them:
    1) Read the MethodSets wiki entry, to better understand what values
    can be stored in an interface and the struct pointer/value
    differences.
    2) Read up on their implementation, if you are the sort who
    understands better by knowing what's going on behind the curtain


    * By the time you need to break this rule, you'll understand why the
    rule says "never."


    HTH,


    On Wed, Dec 19, 2012 at 4:45 PM, John Preston <gizm...@gmail.com>
    wrote:
    I was going through the Go tour, and I hit 68 (Exercise:
    Equivalent
    Binary Trees) and decided to have a go (heh, puns) by myself
    without
    going any further into the slides. I defined a Tree interface,
    made an
    implementation equivalent to the one on slide 68 (called
    StructTree in
    my code), wrote a Compare function and created a test harness.
    However,
    I can't get the thing to work. :(

    Ultimately I think the problems stem from me misunderstanding
    the
    nuances of pointers to interfaces vs. pointers to
    implementations of
    interfaces. I have attached a .tar.gz of my source with
    comments in
    explaining what I think is happening and why I'm so confused.

    The error I am getting at the moment is
    `--> go test
    # tree
    ./compare_test.go:25: cannot use t1 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    ./compare_test.go:25: cannot use t2 (type *StructTree) as type
    *Tree in
    function argument:
    *Tree is pointer to interface, not interface
    FAIL tree [build failed]
    which I believe is because Compare expects *Trees, which are
    not
    pointers to structs implementing trees as I expect, but
    pointers to the
    actual interface. So basically I am confused about the
    difference in
    syntax between a pointer to a struct implementing an interface
    and a
    pointer to an actual interface.

    No spoilers about my code's functionality or other issues yet
    please,
    once I've got this fixed I'd like to try fixing anything else
    by
    myself. :) Thanks in advance.

    --


    --

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 20, '12 at 12:08a
activeDec 20, '12 at 5:12p
posts13
users6
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase