Circular import with structs [duplicate] - go

This question already has answers here:
Registering packages in Go without cyclic dependency
(2 answers)
Closed 7 years ago.
I have a project with several modules in Go. I am having problem with circular imports because of the scenario below:
Details
A module Game contains a struct with the current Game state. Another module (Modifier) is doing some game specific stuff and calculations and therefore modifies the game state. Because of this, Modifier will need the struct Game, but not any methods from Game. Modifier is called from Game and here we have the circular import.
Problem:
Game initiates Modifier
Modifier needs Game struct
It seems to me that this is a common scenario, so I wonder how I should solve it in the best way. My solution would be to create a third module "Structs" which just contains all the structs for the whole application. Is this a good solution?

With the 3rd package option:
yourgame/
state/
state.go
modifier/
modifier.go
main.go
main.go would glue the two components together:
import "yourgame/state"
import "yourgame/modifier"
type Game struct {
state state.State
modifier modifier.Modifier
}
func main() {
// something like:
var game Game
game.modifier.Modify(game.state)
}
This approach is probably too tightly coupled though. Rather than manipulating an essentially global state object, I would try to slice up the data into just what you need for the modifier.
Reasoning in the abstract is hard, so here's a concrete example of what I mean. In your game:
type Object struct {
ID, X, Y int
// more data here
}
type Game struct {
Objects map[int]*Object
}
In your "modifier", let's suppose we had an AI module that moves an object. If all he cares about is the position of a single object you can create an interface:
// in yourgame/modifier
type Object interface {
GetCoordinates() (int, int)
SetCoordinates(int, int)
}
type Modifier struct {}
func (m *Modifier) Update(obj Object) { }
Then we just have to add those methods to our original Object:
type (obj *Object) GetCoordinates() (int, int) {
return obj.X, obj.Y
}
type (obj *Object) SetCoordinates(x, y int) {
obj.X, obj.Y = x, y
}
And now you can pass objects to your modifier without needing a cyclic dependency.
Now if it turns out your "modifier" interface ends up looking almost exactly the same as your game object, then a 3rd package of structs is probably reasonable so you aren't always repeating yourself. For an example consider net/url.

Normally if package B has code that directly reads/modifies A.Type then that code should be in package A.
At least the parts of it if that need direct access should.
To split something between separate packages A and B you'd normal try to isolate an API for access to A.Type that can be expressed as an interface. Then B would define and use this interface and A.Type would implement it (implicitly, without needing to include B's definition of it).
Then something (possibly A, possibily a separate package) would use B by passing an A.Type or *A.Type value as appropriate.
Or depending on your design the relationship could be reversed, with B.OtherType implicitly implementing an interface defined and used by A.
Or both A and B could use each other only through interfaces; it all depends on the details.
E.g. perhaps something like:
package Game // "A"
type State struct {
data int // etc
}
func (s State) IsValid() bool { return true }
func (s *State) ChangeY(arg int) error { return nil }
// …etc…
and:
package Modifier // "B"
type GameState interface {
IsValid() bool
ChangeY(int) error
}
type M struct {
s GameState
//…
}
func New(s GameState) *M {
return &M{s: s}
}
func (m M) DoSomething() {
if s.IsValid() {
// …
}
s.ChangeY(42)
// …etc…
}

I'd define type(Game in this case) and all its methods in same one package. You can't even define methods on type imported from another package according to language spec,
//you should first do
type MyPackageType ImportedType
//and only then
func (foo MyPackageType) Modify() {
...
}

Related

Factory method in golang suffers from cyclic dependency

I realize questions about cyclic dependencies have been answered before, however, the answers usually simply say to merge packages. So long story short, I have an interface which many types will implement. I want to have a way of choosing which one of these types is to be used during runtime using its name. This would also be used for serialization. I read in the name of the class and then instantiate the correct one.
I have used the strategy pattern. There is a Base interface in package A.
package A
import (
"../C"
)
type Base interface {
doStuff(p C.Profile) int
}
type Operation struct {
Base Base
Data int
}
func (o *Operation) execute(p C.Profile) int {
return o.Base.doStuff(p)
}
Then, there are types that implement that interface in package B.
//file Impl1.go
package B
import (
"../C"
)
type Impl1 struct {}
func (b *Impl1 ) doStuff(p C.Profile) int {
...
}
//file Impl2.go
package B
import (
"../C"
)
type Impl2 struct {}
func (b *Impl2 ) doStuff(p C.Profile) int {
...
}
Then in package C i have struct Foo with a field of type Base. This field can point to any of the implementations from package B. We can choose the implementation during runtime. This is the struct that I eventually want to serialize.
package C
import (
"../A"
"../B"
)
type Foo struct {
bar A.Base
baz []Profile
...
}
func (f *Foo) changeBar(name string, data int) {
switch name {
case "Impl1":
f.bar = Operation{Base: B.Impl1{}, Data: data}
case "Impl2":
f.bar = Operation{Base: B.Impl2{}, Data: data}
...
}
EDIT: Also in the C package, we have the Profile, which is the reason A and B packages need to import it.
This code has a cyclic dependency C -> B -> C. An obvious solution would be to move Profile to a different package. But this is not possible because Profile (and many other similar types in the C package) and Foo are very tightly coupled and belong in the same package (maybe not so apparent in this minimal working sample). This is what other answers to these type of questions suggest, but I want to learn how to make it work, using good practices i learned from using other languages.
Another solution would be to somehow move the factory method changeBar to another package and only use it on the outside of the C package (thus avoiding the cycle), passing it results to C as parameters, but there are cases (serialization in particular) where I actually need it on the inside of the C package.
I have put a lot of time into figuring out this issue but all I end up with is either have everything in one huge package or have every single file in a separate package and have everything be exported. In other programming languages, there is the possibility to either have these cyclic dependencies or import one "class" at a time from a package. What is the way to go in go?
You can break the dependency from C to B using a type registry:
package C
import "A"
var TypeRegistry = map[string]func() A.Base {}
func (f *Foo) changeBar(name string, data int) {
if factory, ok:=TypeRegistry[name]; ok {
f.bar=Operation{Base:factory(),Data:data}
}
}
Then register your implementations in any package:
package B
import "../C"
func init() {
C.TypeRegistry["myType"]=func() A.Base { return MyType{}}
}

Generic attribution to field X, present across multiples types

Currently, I'm working with a set of structures, which define multiple versions of a document. Most of the fields are shared across these different versions, and the actual differences are pretty subtle. What I'm trying to do is refactor the code that parses this document. For that, it would be really good if I could generalize some attributions, where I don't need to know exactly what type I'm working to know that the type will have a specific field.
I've thought about using reflection but if I can avoid it I would.
Lets say we have:
type v1 struct{
a int
}
and
type v2 struct{
a int
b string
}
what I would like to do is something like
func main(){
var v1 v1
var v2 v2
foo(v1)
foo(v2)
}
func foo (root interface{}){
root.a = x
}
is it possible? or is there any other way?
edit:
1 - this is not a duplicate of "Get all fields from an interface" as my problem is not to figure out what type I'm dealing with, but to manipulate/treat different types the same way.
2 - this could be a duplicate of "how to write a function to process two types of input data in golang" but the answer provided fails to solve my issue.
Use anonymous fields, methods and interfaces. You can define a new struct that contains all the common properties to all other structs. Then, an interface could be defined over this shared struct, that lists all the methods to handle the common properties. Finally, in the previous structs you only need to replace all the common fields with this new interface. At this point, you are able to write generic functions that take the interface as input and handle internal common fields through exposed methods.
type SettableA interface{
SetA(int)
A() int
}
type sharedA struct {
a int
}
func (s *sharedA) SetA(val int) {
s.a = val
}
func (s *sharedA) A() int {
return s.a
}
type v1 struct {
SettableA
}
type v2 struct {
SettableA
b string
}
func foo(root SettableA) {
root.SetA(5)
}
func main() {
v1var := v1{
SettableA: &sharedA{},
}
foo(v1var)
v2var := v2{
SettableA: &sharedA{},
b: "test",
}
foo(v2var)
fmt.Printf("V1: %v\nV2: %v\n", v1var.A(), v2var.A())
}
Here the interface is not strictly necessary, but it allows you to write a generic function that handles different concrete types.
https://play.golang.org/p/BgxYrbGE426

Immutable Struct in Golang

Is it possible to define an immutable struct in Golang? Once initialized then only read operation on struct's field, no modification of field values. If so, how to do that.
It is possible to make a struct read-only outside of its package by making its members non-exported and providing readers. For example:
package mypackage
type myReadOnly struct {
value int
}
func (s myReadOnly) Value() int {
return s.value
}
func NewMyReadonly(value int) myReadOnly{
return myReadOnly{value: value}
}
And usage:
myReadonly := mypackage.NewMyReadonly(3)
fmt.Println(myReadonly.Value()) // Prints 3
There is no way to mark fields/variables as read only in a generic way. The only thing you could do is marking fields/variable as unexported (first letter small) and provide public getters to prevent other packages editing variables.
There is no way to define immutable structures in Go: struct fields are mutable and the const keyword doesn't apply to them. Go makes it easy however to copy an entire struct with a simple assignment, so we may think that passing arguments by value is all that is needed to have immutability at the cost of copying.
However, and unsurprisingly, this does not copy values referenced by pointers. And the since built-in collections (map, slice and array) are references and are mutable, copying a struct that contains one of these just copies the pointer to the same underlying memory.
Example :
type S struct {
A string
B []string
}
func main() {
x := S{"x-A", []string{"x-B"}}
y := x // copy the struct
y.A = "y-A"
y.B[0] = "y-B"
fmt.Println(x, y)
// Outputs "{x-A [y-B]} {y-A [y-B]}" -- x was modified!
}
Note : So you have to be extremely careful about this, and not assume immutability if you pass a parameter by value.
There are some deepcopy libraries that attempt to solve this using (slow) reflection, but they fall short since private fields can't be accessed with reflection. So defensive copying to avoid race conditions will be difficult, requiring lots of boilerplate code. Go doesn't even have a Clone interface that would standardize this.
Credit : https://bluxte.net/
if you write a functional struct by golang, it must be an immutable struct, eg
you can write maybe struct definite
type Maybe[T any] struct {
v T
valid bool
}
func (m Maybe[T]) Just() T {
return m.v
}
func (m Maybe[T]) Nothing() bool {
return m.valid == false
}
func Just[T any](v T) Maybe[T] {
return Maybe[T]{
v: v,
valid: true,
}
}
func Nothing[T any]() Maybe[T] {
return Maybe[T]{
valid: false,
}
}
the maybe struct is a immutable struct

How to cast interface{} back into its original struct?

I need a way to dynamically cast a struct/interface back to its original object.
I can add methods / functions inside. basically I need something like this:
MyStruct => Interface{} => MyStruct
When on the final conversion I don't know anything about the original struct besides what come inside the struct, so I can't just so:
a.(MyStruct)
You need to know at least the possible types it could be. There's a couple cases, 1. You think you might know what it is. 2. You have a list of possible types it could be, 3. Your code knows nothing about the underlying types.
If you think you know it, you can use type assertion to convert back to the original struct type.
...
package main
import (
"fmt"
)
type MyStruct struct {
Thing string
}
func (s *MyStruct) Display() {
fmt.Println(s.Thing)
}
type Thingable interface {
Display()
}
func main() {
s := &MyStruct{
Thing: "Hello",
}
// print as MyThing
s.Display()
var thinger Thingable
thinger = s
// print as thingable interface
thinger.Display()
// convert thinger back to MyStruct
s2 := thinger.(*MyStruct) // this is "type assertion", you're asserting that thinger is a pointer to MyStruct. This will panic if thinger is not a *MyStruct
s2.Display()
}
You can see this in action here: https://play.golang.org/p/rL12Lrpqsyu
Note if you want to test the type without panicking if you're wrong, do s2, ok := thinger.(*MyStruct). ok will be true if it was successful and false otherwise.
if you want to test your interface variable against a bunch of types, use a switch: (scroll to bottom)
...
package main
import (
"fmt"
"reflect"
)
type MyStruct struct {
Thing string
}
type MyStruct2 struct {
Different string
}
func (s *MyStruct) Display() {
fmt.Println(s.Thing)
}
func (s *MyStruct2) Display() {
fmt.Println(s.Different)
}
type Thingable interface {
Display()
}
func main() {
s := &MyStruct{
Thing: "Hello",
}
// print as MyThing
s.Display()
var thinger Thingable
thinger = s
// print as thingable interface
thinger.Display()
// try to identify thinger
switch t := thinger.(type) {
case *MyStruct:
fmt.Println("thinger is a *MyStruct. Thing =", t.Thing)
case *MyStruct2:
fmt.Println("thinger is a *MyStruct2. Different =", t.Different)
default:
fmt.Println("thinger is an unknown type:", reflect.TypeOf(thinger))
}
}
You can try that out here https://play.golang.org/p/7NEbwB5j6Is
If you really don't know anything about the underlying types, you'll have to expose the things you need through interface functions and call those. Chances are you can do this without knowing anything about the underlying type. If all else fails, you can use the reflect package to introspect your interface object and gather information about it. this is how the json package reads json text and returns populated structs—though this is an advanced topic and expect to sink a lot of time into it if you go this route. it’s best to hide reflection code inside a package with a clean interface(ie the package api).
No: as mentioned in this thread
Go is neither covariant nor contravariant. Types are either equal or they aren't.
You have to either take the structs apart and deal with the pieces, or use reflection.
Type assertions are only "assertions", not "coercions" of any kind.
See also this thread, which reminds us that:
A pointer is one kind of type.
A struct is another kind of type.
An integer is another kind of type.
A floating point number is another kind of type.
A boolean is another kind of type.
The principle of an interface concerns the methods attached to a type T, not what type T is.
An interface type is defined by a set of methods.
Any value that implements the methods can be assigned to an interface value of that type.
That would make the conversion from interface to concrete type quite difficult to do.

Golang struct calling embedded type methods when method has been overloaded

I am trying to learn Go, and I found a good resource here.
The example given on method overloading is reproduced below:
package main
import "fmt"
type Human struct {
name string
age int
phone string
}
type Employee struct {
Human
company string
}
func (h *Human) SayHi() {
fmt.Printf("Hi, I am %s you can call me on %s\n", h.name, h.phone)
}
func (e *Employee) SayHi() {
fmt.Printf("Hi, I am %s, I work at %s. Call me on %s\n", e.name,
e.company, e.phone) //Yes you can split into 2 lines here.
}
func main() {
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi()
}
Is it possible to call the "base" struct's (Human's) methods, eg. sam.Human.SayHi() Downcasting doesn't work (because there is no type hierarchy right?)
You can access the embedded struct of a parent struct by calling the member of the parent with the name of the embedded type's name. That's a mouthful, so it's probably easier to demonstrate it.
sam := Employee{Human{"Sam", 45, "111-888-XXXX"}, "Golang Inc"}
sam.SayHi() // calls Employee.SayHi
sam.Human.SayHi() // calls Human.SayHi
Outputs
Hi, I am Sam, I work at Golang Inc. Call me on 111-888-XXXX
Hi, I am Sam you can call me on 111-888-XXXX
This is the nearest approximation to sane polymorphism with both plain and pure virtual functions that I have found thus far. By the very nature of Go's design and the goal at hand, it is ugly but effective.
package main
import (
"fmt"
)
type I interface {
foo(s string) // Our "pure virtual" function
bar()
}
type A struct {i I}
type B struct {A}
type C struct {B}
// fk receivers, this is a "member function" so I'll use OO nomenclature
func (this *A) init(i I) {
this.i = i // the i contains (internal) pointers to both an object and a type
}
func (this *A) bar() {
this.i.foo("world")
}
func (this *B) foo(s string) {
fmt.Printf("hello %s\n", s)
}
func (this *C) foo(s string) {
fmt.Printf("goodbye cruel %s\n", s)
}
func main() {
var i I
b := &B{}
b.init(b) // passing b as the parameter implicitly casts it to an I interface object
b.bar()
c := &C{}
c.init(c)
c.bar() // c is a pointer to C, so Golang calls the correct receiver
i = b
i.bar()
i = c
i.bar() // Internally, i contains pointers to the C object and the C type,
// so that the correct receiver is called
}
https://play.golang.org/p/4qBfmJgyuHC
In real OO languages, each object of a class with any virtual functions must have a pointer to a virtual function table or a least type that maps to it. So adding an interface member to the base (embedded) struct only wastes an additional machine word for the pointer that will just point to its self.
Alternatively, we could remove the I interface member from A and the have pure virtual member function just accept the implementation as an argument.
type I interface {
foo(s string)
bar(i I)
}
type A struct {}
type B struct {A}
type C struct {B}
func (this *A) bar(i I) {
i.foo("world")
}
https://play.golang.org/p/9gvaCuqmHS8
But at this point, foo is no longer a pure virtual function, API users could pass any value whose type implements I, and the whole OO concept is broken. The object pointer portion of the I interface passed to bar doesn't need to be the same as this, but then again we didn't need to pass that same value using an init() function, but at least only an API user in the same package would be allowed to set it.
At this point, we have transitioned to the Go way of doing things: compositional programming with dependency injection. This is what Ken Thompson and the other designers thought was a better way to go -- at least for their stated goals. While it is vastly inferior in MANY respects, it does create many advantages and I won't argue those points that here.

Resources