Implementing interface from different package golang - go

I'm having some issues trying to implement an interface, defined in a different package in golang. I have made a minimal recreation of the problem below
Interface:
package interfaces
type Interface interface {
do(param int) int
}
Implementation:
package implementations
type Implementation struct{}
func (implementation *Implementation) do(param int) int {
return param
}
Main.go:
package main
import (
"test/implementing-interface-in-different-package/implementations"
"test/implementing-interface-in-different-package/interfaces"
)
func main() {
var interfaceImpl interfaces.Interface
interfaceImpl = &implementations.Implementation{}
}
Error message:
test/implementing-interface-in-different-package
./main.go:10:16: cannot use implementations.Implementation literal (type
implementations.Implementation) as type interfaces.Interface in assignment:
implementations.Implementation does not implement interfaces.Interface (missing interfaces.do method)
have implementations.do(int) int
want interfaces.do(int) int
Is it possible to implement an interface from a different package?
Thanks!

The problem is that your do function is not exported from the implementations package because it starts with a lower-case letter. Thus from the point of view of the main package, the variable interfaceImpl does not implement the interface because it cannot see the do function.
Rename your interface function to upper-case Do to resolve the problem.

Related

In GoLang, how do you isolate packages that return more than a primitive value?

If I have a requests package that defines an interface TextExtractor with a GetText method that returns a Text type, the implementations must fulfill the TextExtractor contract exactly, and they are forced to import the Text type.
I have two possible implementations of TextExtractor - one that uses AWS Comprehend and one that uses AWS Textract.
aws_comprehend.go
package aws_comprehend
type AwsComprehend struct{}
func (a *AwsComprehend) GetText() *Text {
// do some stuff with aws comprehend...
return &Text{
Text: "text",
Language: "language",
}
}
type Text struct {
Text string
Language string
}
request.go
package requests
import "fmt"
type TextExtractor interface {
GetText() *Text
}
type Text struct {
Text string
Language string
}
func HandleRequest(textExtractor TextExtractor) {
text := textExtractor.GetText()
fmt.Println(text)
}
main.go
package main
import (
"aws_comprehend"
"requests"
)
func main() {
textExtractor := new(aws_comprehend.AwsComprehend)
requests.HandleRequest(textExtractor)
// this does not work:
// cannot use textExtractor (variable of type *aws_comprehend.AwsComprehend) as
// requests.TextExtractor value in argument to requests.HandleRequest:
// *aws_comprehend.AwsComprehend does not implement requests.TextExtractor
// (wrong type for method GetText)
// have GetText() *aws_comprehend.Text
// want GetText() *requests.Text
}
I understand why this doesn't work. It's because GoLang doesn't support Covariant Result Types. But my question is, what is the standard way to code this situation? The fact that GoLang provides implicit interfaces means that isolating packages is very easy: the calling package defines the interfaces that it uses, and it is passed implementations that fulfill those interfaces. This means that packages don't have to reference each other at all. But if a package defines an interface that returns anything more than a primitive value, then you have to deliberately share those value types. The code above would be fine if GetText returned a string. But the fact that it returns a struct or another interface, means the code can't be written this way.
I want the requests package not to know anything about the aws_comprehend package. This is because I have two implementations of the TextExtractor interface: One that uses AWS Comprehend, and one that uses AWS Textract. I also would prefer not to include a "intermediate" package that has interfaces that both the requests package and the aws_comprehend package inherit from. If both packages have to inherit the same interface, then it seems like it's just indirect coupling to me and it ruins the idea of a implicit interfaces.
I understand that GoLang is very opinionated - So what is the standard way to solve this problem?
first, your file layout is not valid. you cant have two files in the same
folder, with different packages. so below is a corrected layout. also I removed
all pointers, because they aren't needed for this example and are just distracting.
Finally, I updated the method to return the correct type, so that the code
actually compiles:
aws_comprehend/aws_comprehend.go:
package aws_comprehend
import "hello/requests"
type AwsComprehend struct{}
func (AwsComprehend) GetText() requests.Text {
return requests.Text{}
}
requests/request.go:
package requests
import "fmt"
type TextExtractor interface {
GetText() Text
}
type Text struct {
Language string
Text string
}
func HandleRequest(textExtractor TextExtractor) {
text := textExtractor.GetText()
fmt.Println(text)
}
main.go:
package main
import (
"hello/aws_comprehend"
"hello/requests"
)
func main() {
var textExtractor aws_comprehend.AwsComprehend
requests.HandleRequest(textExtractor)
}

How can I (or should I) use Go interfaces for picking one of two packages? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
OK, I'm not quite getting it....
I have 2 modules I crafted with identical functions (in different files of course):
package mod1
func MyFunc() string {
return "mod1.Myfunc"
}
func Func2() string {
return "mod1.Func2"
}
package mod2
func MyFunc() string {
return "mod2.MyFunc"
}
func Func2() string {
return "mod2.Func2"
}
I have an interface defined correctly, (I think) in a third package:
package types
type MyType interface {
MyFunc() string
Func2() string
}
I have code which can pick whether I want to use mod1 or mod2, but I'm not quite understanding what I should have this code return:
func mypicker() ????{
}
Then in main, I want to somehow call either mod1.MyFunc() or mod2.MyFunc() based on
mypicker, without knowing which it is.... something like this:
func main() {
p := mypicker()
fmt.Print(p.MyFunc())
// and later
fmt.Print(p.Func2())
}
I read that interfaces are like void *, but clearly I'm not getting the complete picture.
Pointers to docs, code, anything useful would be great.
Interfaces should be used with types, not just plain functions. You can start by reading the Tour of Go sequence on interfaces. Here's an example close to your question's original code:
Given the interface:
type MyType interface {
MyFunc() string
Func2() string
}
You'd have a type:
type MyType1 struct{}
func (mt MyType1) MyFunc() string {
return "MyType1.MyFunc"
}
func (mt MyType1) Func2() string {
return "MyType1.Func2"
}
And similarly:
type MyType2 struct{}
func (mt MyType2) MyFunc() string {
return "MyType2.MyFunc"
}
func (mt MyType2) Func2() string {
return "MyType2.Func2"
}
And now, if you have some function that takes your MyType interface:
func Foo(m MyType) {
fmt.Println(m.Func2())
fmt.Println(m.MyFunc())
}
You could call it with either of your types that implements that interface:
m1 := MyType1{}
Foo(m1)
m2 := MyType2{}
Foo(m2)
Here's a Go Playground link where you can try this in action.
As for "picking a type", perhaps you mean something like this:
var mi MyType
if (... some condition ...) {
mi = m1
} else {
mi = m2
}
// Now you can do with mi whatever its interfaces permits,
// like calling mi.Func2(), etc.
Regarding the "picking one of two packages" part of the question:
Interfaces are implemented by types; they're orthogonal to packages and modules. In other words, an interface and types that implement it can all be in the same package, or in different packages, or in different modules.
You have to be careful with terminology. Go modules and Go packages are very different, even though both can be contained by directories. Basically, a directory is a package if it has at least one Go file in it and no go.mod file. If a directory has a go.mod file in it then it's recognized as a module. Generally, a whole project can be a single module with the go.mod file at the root of the project and that's sufficient. Assuming this is your case, move forward thinking that every sub-directory is just a package within that single module.
An interface doesn't really have to do with modules or packages, it has to do with types. The reason being is that an interface defines behavior, meaning it defines what methods are required for a type to accurately implement that interface. In your case, you defined both functions declared in your interface BUT they are NOT METHODS because they are top-level functions only attached to the package. In order for a function to be a method, it must be "attached" to a type. Then, that type becomes a valid implementation of that interface.
This...
package mod1
func MyFunc() string {
return "mod1.Myfunc"
}
func Func2() string {
return "mod1.Func2"
}
Needs to become this...
package mod1
type MyTypeImpl struct {}
func (m MyTypeImpl) MyFunc() string {
return "mod1.Myfunc"
}
func (m MyTypeImpl) Func2() string {
return "mod1.Func2"
}
The naming could be improved greatly but the point is that the above function declaration syntax is how you "attach" a function to a type, making it a method, which allows that MyTypeImpl struct to now be a valid implementation of your MyType interface.
Now you can call the interface methods without regards to which underlying type is actually the implementation:
var iType MyType
iType = MyTypeImpl{}
iType.MyFunc()
Notice that in that last line, it does not matter that we used MyTypeImpl to implement the interface. Once the implementation is assigned to a variable with the interface type, we just work with the interface and forget the underlying implementation. When we call iType.MyFunc(), Go will call the proper method from the underlying implementation.
If we had 100 different structs that implemented the MyType interface as MyTypeImpl does, they could all work for the right side of that iType = MyTypeImpl{} line. That's the point of an interface, to define it once and then use it without regard to what underlying struct is actually implementing it.

How to use a type parameter in an interface method?

I am trying to write a sample program to try and implementing the a data structure using Go generics.
As part of this I want to define a iterator interface. I have the following code:
package collection
type Iterator interface {
ForEachRemaining(action func[T any](T) error) error
// other methods
}
It keeps giving me following error
function type cannot have type parameters
Moving the type parameter to the method also doesn't work:
type Iterator interface {
ForEachRemaining[T any](action func(T) error) error
// other methods
}
Gives error:
methods cannot have type parameters
Is there any way to define generic interface
As the error suggests, methods cannot have type parameters of their own as per the latest design. However, they can use the generics from the interface or struct they belong to.
What you need is to specify the type parameter on the interface type as follows:
type Iterator[T any] interface {
// ...
}
and then use the T as any other type parameter in methods within the interface body. For example:
package main
import "fmt"
type Iterator[T any] interface {
ForEachRemaining(action func(T) error) error
// other methods
}
func main() {
fmt.Println("This program compiles")
}
Try it on Go playground.

how to use function of unexported struct [duplicate]

This question already has an answer here:
Is there a way to create a function using unexported type as parameter in Golang?
(1 answer)
Closed 3 months ago.
I have a package where I have unexported struct and exported New function to create it and exported function that runs on this struct (as advised for example here: Return an unexported type from a function).
If I run the function in the same place the New is called I can run the package function but I am unable to send this entity to another function.
what is the best way to achieve this behavior without the need to have all my code in one function
this for example works:
client := package.New()
client.Foo()
but this cannot work:
client := package.New()
hello(client)
func hello(client interface{}) {
client.Foo()
}
What your hello function essentially needs is something that has a Foo function. That's why go has interfaces. There's nothing wrong with returning an unexported type (in fact, it's common and often the right thing to do). What I'd do is this:
package foobar
// whatever thing that has a Foo function
type FClient interface {
Foo()
}
func Hello(client FClient) {
client.Foo() // will work
}
The reason why you'd do it like this is to be able to unit-test this code:
package foobar_test
import (
"testing"
)
type testFC struct {
callCount uint64
}
// implement interface
func (t testFC) Foo() {
testFC.callCount++
}
func TestHello(t *testing.T) {
client := testFC{}
Hello(client)
if client.callCount != 1 {
t.Fail("dependency not called")
}
}
Of course, for more complex dependencies you'd use tools like mockgen or stuff like that, but you get the idea. By definition, a UNIT test focuses on a single UNIT of code. The last thing you'd need to do to test a package unit is to instantiate a type from another package. You should be able to mock everything your code depends on. The best way to do so is interfaces.

Is it possible to implement an interface with unexported methods in another package?

I have written an interface for accounting system access. I would like to hide specific implementations of the interface from my program as I will only ever have one "active" accounting system. So I planned on making the methods of the interface unexported (hidden), and then having exported functions native to the base package that call a the same function from a local adapter.
package accounting
import "errors"
type IAdapter interface {
getInvoice() error
}
var adapter IAdapter
func SetAdapter(a IAdapter) {
adapter = a
}
func GetInvoice() error {
if (adapter == nil) {
return errors.New("No adapter set!")
}
return adapter.getInvoice()
}
__________________________________________________
package accountingsystem
type Adapter struct {}
func (a Adapter) getInvoice() error {return nil}
__________________________________________________
package main
import (
"accounting"
"accountingsystem"
)
function main() {
adapter := accountingsystem.Adapter{}
accounting.SetAdapter(adapter)
}
The problem with this is that the compiler complains, due to not being able to see the implementation of getInvoice() by accountingsystem.Adapter:
./main.go:2: cannot use adapter (type accountingsystem.Adapter) as type accounting.IAdapter in argument to accounting.SetAdapter:
accountingsystem.Adapter does not implement accounting.IAdapter (missing accounting.getInvoice method)
have accountingsystem.getInvoice() error
want accounting.getInvoice() error
Is there any way of being able to implement an interface with unexported methods in another package? Or am I thinking about this problem in a non-idiomatic way?
You can implement an interface with unexported methods using anonymous struct fields, but you cannot provide your own implementation of the unexported methods. For example, this version of Adapter satisfies the accounting.IAdapter interface.
type Adapter struct {
accounting.IAdapter
}
There's nothing that I can do with Adapter to provide my own implementation of the IAdapter.getInvoice() method.
This trick is not going to help you.
If you don't want other packages to use accountingsystem.Adapter directly, then make the type unexported and add a function for registering the adapter with the accounting package.
package accounting
type IAdapter interface {
GetInvoice() error
}
---
package accountingsystem
type adapter struct {}
func (a adapter) GetInvoice() error {return nil}
func SetupAdapter() {
accounting.SetAdapter(adapter{})
}
---
package main
func main() {
accountingsystem.SetupAdapter()
}

Resources