How cheaply can I convert types (structs and interfaces)?

425 views
Skip to first unread message

doug livesey

unread,
Jan 29, 2016, 3:12:02 PM1/29/16
to golang-nuts
Hi -- I've hit a bit of a downer as I've realised that Go won't do generics, or even function overloading, as I'd assumed.
So now I'm trying to think my way around the problem.
To that end, is there a way to really cheaply 'cast' between types? I know about type conversion, but that's for simple types, and there's type assertion, but that's expensive, isn't it?
Any advice on how to approach this issue would be really appreciated!
Thanks,
Doug.

James Bardin

unread,
Jan 29, 2016, 3:22:32 PM1/29/16
to golang-nuts


On Friday, January 29, 2016 at 3:12:02 PM UTC-5, doug livesey wrote:
Hi -- I've hit a bit of a downer as I've realised that Go won't do generics, or even function overloading, as I'd assumed.
So now I'm trying to think my way around the problem.

It might help if you try to describe what the problem is. It's hard to answer this question in the abstract. 
 
To that end, is there a way to really cheaply 'cast' between types? I know about type conversion, but that's for simple types, and there's type assertion, but that's expensive, isn't it?


Type assertions are very cheap, as you're really just verifying the type of what is already there.  Maybe you're thinking of reflection?

doug livesey

unread,
Feb 1, 2016, 1:58:11 AM2/1/16
to golang-nuts
Hi -- thanks very much for your replies, and sorry for the lateness of mine -- I took a frustration break of a couple of days! :)
I have a tree of objects, the only existing bits of which currently are Config, Runner, and World.
These are composed in a main function, based on command-line flags and database records.
Persisting these is handled in a repo module, which needs to be able to get at fields of the objects to compose them into model objects which are then persisted. And it will need to do that in reverse, too, eventually.
And these objects are all going to have to interact with each other as part of the running program, as well as with a great number of other objects.
I want to be able to develop and test each module and object in complete isolation from everything else -- which is, of course, good practice.
However, I can't see a way to do this without generics.
I want to pass an object (which happens to be a Runner) to a repo object, which can assume that it can access its POD fields, and its struct fields, like World. Of course, for the isolation to be complete, the struct fields like World should also be abstractions. But any attempt I've made to achieve this without coupling has failed to compile.
I tried to work around this by using genny with `go generate`, but then ran into the wall of no function overloading.
How do other people go about removing the coupling that I'm struggling to eliminate?

--
You received this message because you are subscribed to a topic in the Google Groups "golang-nuts" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/golang-nuts/K6CTEtErpdk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to golang-nuts...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Tamás Gulácsi

unread,
Feb 1, 2016, 2:04:32 AM2/1/16
to golang-nuts
What's the matter with interfaces?
The underlying types (struct) are indifferent, till they implement the needed methods.

doug livesey

unread,
Feb 1, 2016, 2:11:22 AM2/1/16
to golang-nuts
I rather better described the issue I'm having here: https://groups.google.com/forum/#!topic/golang-nuts/ULb_ggkGATA

To recap: this code:

package main

import (
"fmt"
)

type Child struct {
name string
}

type Parent struct {
child *Child
}

func (c *Child) Name() string {
return c.name
}

func (p *Parent) Child() *Child {
return p.child
}

type CI interface {
Name() string
}

type PI interface {
Child() CI
}

func main() {
c := &Child{name: "Horace"}
p := &Parent{child: c}
pi := PI(p)
fmt.Println(c, p, pi)
}

Gives this error:
test/scratch.go:34: cannot convert p (type *Parent) to type PI:
*Parent does not implement PI (wrong type for Child method)
have Child() *Child
want Child() CI

Because the compiler wants Child method to be coupled to the Child type. 

On 1 February 2016 at 07:04, Tamás Gulácsi <tgula...@gmail.com> wrote:
What's the matter with interfaces?
The underlying types (struct) are indifferent, till they implement the needed methods.

Ian Davis

unread,
Feb 1, 2016, 5:49:59 AM2/1/16
to golan...@googlegroups.com
You defined a PI as something that has a method like this:
 
Child() CI
 
But the method you implemented on Parent is:
 
Child() *Child
 
Just change it so it returns a CI:
 
func (p *Parent) Child() CI {
    return p.child
}
 
It's not coupled to the Child type but to CI which is what you specified.
 
Ian

doug livesey

unread,
Feb 1, 2016, 5:57:55 AM2/1/16
to golang-nuts
Ah, but then the Parent needs to know about the CI Child interface.
I was hoping to use interfaces to allow every module not to need to know about any other modules. So a CI to a repo would be defined in there, and a CI to a renderer would be defined in there, and neither module need know about the Child struct, and the Child and Parent structs need know nothing about the repos, rendererers, or the interfaces they specify.
It could well be (probably is) that my thinking is rather muddy on this.
In Ruby, for instance, interfaces are implicit -- that's what I'm aiming for here, if possible.
You could do something like it in C++ using a trick I saw in a Google video with generics, but it was a PITA to keep doing.
I'm having a quick look at Rust to see if it can be done, there.
It could well be that I need to rethink some of my assumptions!

--

Roberto Zanotto

unread,
Feb 1, 2016, 10:35:40 AM2/1/16
to golang-nuts
Interfaces in go are implicitly satisfied and don't require the "implements" declaration. This allows to have separated modules (packages not importing each other, possibly in different repositories) that can work together. Of course the modules must agree on the interfaces to use (define the same common interfaces in each package).
Reply all
Reply to author
Forward
0 new messages