The example gives me a better understanding of what you are doing, though 
still not much understanding as to *why *you are doing it this way. 
Usually, if I feel that code has a "smell" in Go, there is a way to rethink 
the basic design resulting more "natural" code. But without a full 
understanding of the real situation, it is impossible to say if that 
applies here. But lets assume for now that you must have multiple packages 
that all contain functions that return a common struct.
 

> But I do not like:
>
>
>    1. Having a package just to hold a single type,
>
> Personally, I don't see anything inherently wrong with this. If you *must 
*multiple packages that all need the type, then it should be in a package 
separate from those. In many cases there would be functions that could also 
go in package `state`, but if not, then that's ok too.

2. The consumer package is accepting a concrete type and depends on it - 
> seems this one can not be avoided since there is nothing like structural 
> typing for structs in Go.
>

Your example does feel a bit awkward, but, again, I don't have enough 
information on what is really being achieved to suggest a completely 
different model.  

But I will take a shot in the dark. Think interfaces? Perhaps the 
state.State type returned by Clone() could be an interface? This does not 
solve the problem of having to define the interface in a separate package, 
and I would only use an interface if there was a compelling reason to do 
so. 

Taking a further leap,why "Clone()" at all? What do you do with state.State 
in package consumer? Does it have to be a struct for some reason? If you 
could define a set of functionality that a consumer needs from state.State, 
you could then have Concrete1, Concrete2, and Concrete3 all implement that 
functionality. Then consumer can just use them directly as interfaces ... 
or perhaps that is using them indirectly. Anyway, I hope that is somewhat 
comprehensible. 

Good Luck
 - Jake

On Tuesday, April 24, 2018 at 1:49:45 AM UTC-4, Kaveh Shahbazian wrote:
>
> @Jake @Bryan Thanks!
>
> Current solution I use:
>
> A package that holds the shared data type State:
>
> package state
>
> type State struct {
>     Latitude  float64
>     Longitude float64
>     Mark      string
>     Name      string
>     // ...
> }
>
> Three packages with different implementations and algorithms:
>
> package concrete1
>
> import (
>     "gitlab.com/dc0d/gist/2018/Q1/draft/cmd/draft/state"
> )
>
> type Concrete1 struct{}
>
> func (c *Concrete1) Clone() (*state.State, error) { panic("N/A") }
>
> And:
>
> package concrete2
>
> import (
>     "gitlab.com/dc0d/gist/2018/Q1/draft/cmd/draft/state"
> )
>
> type Concrete2 struct{}
>
> func (c *Concrete2) Clone() (*state.State, error) { panic("N/A") }
>
> And:
>
> package concrete3
>
> import (
>     "gitlab.com/dc0d/gist/2018/Q1/draft/cmd/draft/state"
> )
>
> type Concrete3 struct{}
>
> func (c *Concrete3) Clone() (*state.State, error) { panic("N/A") }
>
> And the consumer package, which will be given a concrete implementation 
> based on some logic (this is where "Accepting interfaces" is happening):
>
> package consumer
>
> import (
>     "gitlab.com/dc0d/gist/2018/Q1/draft/cmd/draft/state"
> )
>
> func Use(cln cloner) {}
>
> type cloner interface {
>     Clone() (*state.State, error)
> }
>
> The part in question is the *state.State data type. This is the best I 
> could come up with.
>
> But I do not like:
>
>
>    1. Having a package just to hold a single type,
>    2. The consumer package is accepting a concrete type and depends on it 
>    - seems this one can not be avoided since there is nothing like structural 
>    typing for structs in Go.
>
>
> There might be a better way to do this.
>

-- 
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+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to