Access private fields of a package in golang using reflect [duplicate] - go

This question already has answers here:
How to access unexported struct fields
(4 answers)
Closed 1 year ago.
I am writing a unit test for a package in golang. I need to create a variable of private field type which resides in a different package to pass it as a parameter to the function that I am testing.
package : go/abc/a.go
type newType int
package : go/edf/b.go
import "go/abc"
func init(abc newType){
// ommitted for brevity
}
Now I am writing unit test for b.go say
package : go/edf/b_test.go
func TestInit(){
// Now I need to create a variable of private field type newType in abc package
// for passing as parameter to the init function....
}
Is it possible to achieve this using reflect or packages package in golang

I need to access a private field in a package
You cannot do this. The sole purpose of being unexported (what you call private) is to be inaccessable from outside.

Related

How to create abstract structure implementations [duplicate]

This question already has answers here:
Implementing an interface with a wider method signature
(3 answers)
How to implement interface method with return type is an interface in Golang
(1 answer)
Closed 4 months ago.
The community reviewed whether to reopen this question 4 months ago and left it closed:
Original close reason(s) were not resolved
I've got a slice of steps []*Steps where each step has a type and a custom payload depending on it:
type Step struct {
ID string
Name string
Type StepType // Enum: StepA | StepB
Action StepAction // interface implemented by either ActionStepA | ActionStepB
// Other common fields
}
// StepAction is an interface implemented by either ActionStepA | ActionStepB
type StepAction interface {}
type ActionStepA struct {FieldA string} // Fields specific to step A
type ActionStepB struct {FieldB string} // Fields specific to step B
Depending on the Type, the Action will be a different struct: either ActionStepA or ActionStepB which just hold their own step-specific fields.
To Execute these steps, I have a StepExecutor interface:
type StepExecutor interface {
Execute(StepAction) error
}
Ideally, I'd like to have a StepExecutor implementation per StepType which contains the business logic and knows how to execute its type. E.g. have StepAExecutor() which executes ActionStepA and StepBExecutor which executes ActionStepB.
How can I achieve something like this in GOlang? I guess what I need is a concept similar to Abstract Classes?
for _, step := range steps {
executor := getExecutorForStep(step) // returns a StepExecutor type
executor.Execute(step.Action)
}
// ERROR HERE:
fun getExecutorForStep(step *Step) StepExecutor {
switch step.Type {
case StepA: return &StepAExecutor{}
case StepB: return &StepBExecutor{}
}
}
I tried the above but I'm getting errors as the StepExecutor "implementations" are not actually implementations as they have mismatched method signatures:
StepExecutor expects StepAction for the Execute method
StepAExecutor expects ActionStepA for the Execute method
StepBExecutor expects ActionStepB for the Execute method
If go doesn't allow for such a case, I'm happy to redo the architecture with a proper more common one. Let me know if you have any suggestions. I understand that in golang, methods signatures must match literally - I'm just unsure how I can properly structure this problem. I might be in need of a re-architecture.

Grouping exported types by name [duplicate]

This question already has an answer here:
Ref "is not a type" - storing a type in a struct
(1 answer)
Closed 4 years ago.
I have this in a file:
import (
"huru/routes/login"
"huru/routes/nearby"
"huru/routes/person"
"huru/routes/register"
"huru/routes/share"
)
// Handlers
type RegisterHandler = register.Handler
type LoginHandler = login.Handler
type NearbyHandler = nearby.Handler
type ShareHandler = share.Handler
type PersonHandler = person.Handler
this works, but I am wondering if there is a way to group them, like so:
// PSEUDO CODE
var Handlers = {
Register : register.Handler
Login : login.Handler
Nearby : nearby.Handler
Share : share.Handler
Person : person.Handler
}
note yes that's bogus syntax but hopefully you know what I mean. What I am trying to do is export a namespace, so I can do this:
import (
"huru/x"
)
x.Handlers.Register{}
instead of:
x.RegisterHandler{}
Could you make Handlers.Register a function instead? Then you could register them to a global map or something.

How to avoid import cycles in mock generation?

Simple example.
I have package xxx. This package contains:
struct A
interface B which is a field of A
struct C which is an argument in method of B
type A struct {
SomeField B
}
type B interface {
SomeMethod(c C)
}
Now imagine I want to create unit test for structure A and mock dependency B. For creating mock I am using mock generator. All mocks are stored in the common "mocks" folder.
The problem is that generated mock has a dependency on xxx package. This is happening because SomeMethod of interface B has argument xxx.C.
Whenever I try to import my mock structure in a_test.go it fails because of cycle import problem. xxx package importing mocks package in the a_test.go. and mocks package imports xxx package in my generated mock.
I need a peace of advice, what is the best workaround for this? Maybe my approach is not idiomatic enough. Where do you store your mocks?
You need to put your test under a different package.
a.go is under package xxx
a_test.go is under package xxx_test
a_mock.go is under package xxx_mock
This way a_test.go will be dependent on xxx and xxx_mock and will not cause dependency cycle.
Also, a.go and a_test.go can be under the same folder, like this:
xxx/
- a.go
- a_test.go
mock/
- a_mock.go
Since
interface
struct
user code
unit test for the user code
are all in the same package, the interface should be considered as "in-package" interface, which is invisible for code in other package. So, the mock for this interface should be IN THE SAME PACKAGE as the interface itself.
Conclusion:
interface
struct
user code
unit test for the user code
mock for the interface
PUT ALL OF THEM IN THE SAME PACKAGE.
So put the mock code generated by gomock into the same package as the interface, but not "mock" package. Example(windows version):
mockgen -source=.\foo\bar.go -destination=.\foo\bar_mock.go -package=foo
Compiling a_test.go as different package (ex. a_test) will resolve the cirucular import issue.
This is the io_test.go example from go language source. Associate question with example by replacing package xxx with package io and a_test with io_test.
//io_test.go
package io_test
import{
. "io" //wildcard import
}
// io_test code
However there wont be access to non-exported type in package io. To make the non-exported type to exported type we could add a file export_test.go and define a exported and assign non-exported type to exported type.
//export_test.go
package io
// exported for test
var IOExportedType= ioNonExportedType
Use a top level package that all other packages import from. Put your interfaces there.
For instance:
domain/
interfaces.go
a/
mock.go
b/
mock.go
c/
mock.go
a, b and c should import from domain so they don't have any dependencies on each other. You will use duck typing to implement the interfaces of the domain package in your mocks.
Here's an actual use case using your example:
domain/interfaces.go:
type A interface {
Foo()
}
type B interface {
Bar() string
}
type C interface {
Baz() string
}
a/mock.go:
type A struct {
SomeField domain.B
}
// ...
b/mock.go:
type B struct {
SomeMethod(c domain.C)
}
// ...
c/mock.go:
type C struct {}
// ...
That should compile just fine, because all the mocks import from the top level domain package, and they all implement the respective interfaces.
In case of avoiding self referencing in Go 1.17
Add this arg
-self_package github.com/xxx
So
mockgen -source=<srcName>.go \
-package <pkgName> \
-self_package github.com/<user>/<repo>/<pkgName> \
-destination <dest>.go

Golang Circular import structs

My code is simple.
Project/
main.go
pokemons/
pokemon.go
pokeTrainers/
pokeTrainer.go
I have some Pokemon trainers which are defined like this :
package pokeTrainers
import "../pokemons"
type PokeTrainer struct {
name string
pokemon []Pokemon
}
And some Pokemon :
package pokemons
import "../pokeTrainers"
type Pokemon struct {
name string
pokeTrainers PokeTrainer
}
main package is:
package main
import (
"fmt"
"./pokemons"
"./pokeTrainers"
)
func main() {
fmt.Printf("ERROR CIRCULAR IMPORT")
As always when I have an error, I copy-paste it on google. I learn what's a circular import and how people fix it with interface to use methods from another package without import it. But in my case, the problem is not to use methods but a real Type defined in another package.
So you will probably say: "Man you are dumb ! You just have to put everything on the same package and it's fine !"
Sorry, I come from Java and I would like that my code stays clean. ;)
I saw this link which suggest to use a third party packages ? But you have to imagine that I don't have only pokemon and pokeTrainer, I have many more packages with a type inside and a lot of methods..
What do you think ? How can I fix this error proprelly ? I'm a beginner in Go
Either use a single package, so no import is needed.
Or designate one of your packages to be a "master", and put "everything" that is needed from both packages into this "master", and so only the other package needs to import "master" by definition (and "master" doesn't need to import the other).
Or you have to create a 3rd package for the stuff that is needed from both, and your 2 current packages only have to import this 3rd common package.
P.S. And don't use relative imports. Always use the complete package path.
I suggest you using interface for Pokemon. Perhaps you will add a several type of a pokemon and PokeTrainer should to train each one.
Example:
poketrainer.go
package pokeTrainers
type IPokemon interface {
train() error
}
type PokeTrainer struct {
name string
pokemon []IPokemon
}
pokemon.go
package pokemons
import "github.com/pokemonWorld/pokeTrainers"
type Pikachu struct {
name string
sensei *PokeTrainer
}
func (o *Pikachu) train() error {
// your code here
}
One extra point of a recommendation - use a pointer of structure but not as a value.

Why can methods in Go only be declared on types defined in the same package?

The Go Tour says the following:
You can only declare a method with a receiver whose type is defined in the same package as the method. You cannot declare a method with a receiver whose type is defined in another package (which includes the built-in types such as int).
Is there a reason for this other than avoiding everyone building their own methods off int and string? I've Googled around, but can't find anything referencing it.
The reason is that if you could define methods on other packages' types, you could modify the behavior of other packages. This is because the method set of a given type can have an effect on how values of that type are used.
Consider, for example, the fmt.Println function. When you pass an argument to fmt.Println, it will print a string representation of that value based on a set of rules. One of those rules is that if the type of the value has a String() string method (that is, it implements the fmt.Stringer interface), then that method will be called in order to obtain the string representation of the value.
Thus, imagine that we have a package, foo, and that package has a type, FooInt, defined as follows:
type FooInt int
Now imagine that this package also has a function, PrintFooInt:
func PrintFooInt(f FooInt) { fmt.Println(f) }
This will print the integer value of f. But let's say that you (in a different package, say main) were able to add methods to FooInt. Then you could do this:
func (f FooInt) String() string { return "foobar!" }
This would actually change the behavior of foo.PrintFooInt, which shouldn't be possible from outside the package.

Resources