Doesn't see public functions of a struct Golang - go

I don't see the public method of the struct that I defined.
Can someone please let me understand why?
Here is the code:
// DataSaver.go:
package DataStorage
import (
"fmt"
"os"
)
type DataSaver struct {
// doesn't relevant to my question
fileName string
file *os.File
}
func PrintStr() {
fmt.Println("hello")
}
Then, I have a main method in other class. I initialized the struct and I wanted to call to PrintStr() function. However, I can't call to this method. Why?
Thank you!

That is not a method, it is just a function.
Import DataStorage (you should make it lower case) then you can call DataStorage.PrintStr()

I had a play around myself with this, and there are a few things to be careful of:
Make sure you import the package properly with respect to your GOPATH, e.g.
import "github.com/some-repo/datastorage"
And ensure that your packages/repos are in your GOPATH and in the correct directories (go is very fussy about how you do this)
Refer to your function using the package name like so:
func main(){
DataStorage.PrintStr()
}
The other poster is correct in that go conventions are to keep package names in lowercase.

Seems you dont have the concept of method receiver yet. Your method for the struct should be defined as below :
func (this DataSaver)PrintStr() {
fmt.Println("hello")
}
or
func (this *DataSaver)PrintStr() {
fmt.Println("hello")
}
which one you choose depends on you want to call the method on a pointer or not;

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)
}

Implementing interface from different package golang

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.

Adding a method for existing type in Golang: how to rewrite return value's type

I want to extend existing goquery.Selection type with my own method and be able to use it from package's selectors. I know that I cannot "patch" existing method -- I need to create a new one. But how do I can force the existing package functions to use my new type? Something I'm missing in general or there's no "nice" way to do it and it's better to use a function?
package main
import (
"fmt"
"github.com/PuerkitoBio/goquery"
)
type customSelection goquery.Selection
func (s *customSelection) CustomMethod() int {
return 1
}
doc.Find("*").Each(func(i int, s *goquery.Selection) {
fmt.Println(s.CustomMethod()) // does not works since its still "goquery.Selection"
// how do I can get a result with customSelection type here?
})
Since inheritance is not supported, the best practice is to embed the non-local type into your own local type, and extend it.
In the Design Patterns lingo its better known as composition:
https://en.wikipedia.org/wiki/Composition_over_inheritance
You can use function instead of method:
func customFunc(s *goquery.Selection) int {
return 1
}
...
fmt.Println(customFunc(s))

How to access flags outside of main package?

We parse flags in main.go which is in main package, of course. Then we have another package where we want to read some flag's value.
flags.Args() work fine, it will return all non-flag values.
But I cannot figure out to how read already parsed value for a flag in a package other than main.
Is it possible?
Thanks
Amer
I had the same requirement recently and I wanted a solution that avoided calling flag.Parse repeatedly in init functions.
Perusing the flag package I found Lookup(name string) which returns a Flag which has a Value. Every built in Value implements the flag.Getter interface. The call chain looks like this:
flag.Lookup("httplog").Value.(flag.Getter).Get().(bool)
If you mistype the flag name or use the wrong type you get a runtime error. I wrapped the lookup in a function that I call directly where needed since the lookup and get methods are fast and the function is not called often. So the main package declares the flag.
// main.go
package main
import "flag"
var httplog = flag.Bool("httplog", false, "Log every HTTP request and response.")
func main() {
flag.Parse()
// ...
}
And the utility package, which is decoupled from main except for the flag name, reads the flag value.
// httpdiag.go
package utility
import "flag"
func logging() bool {
return flag.Lookup("httplog").Value.(flag.Getter).Get().(bool)
}
You can define the var storing the flag in the separate package, as an exported variable, then call the flag parsing in the main package to use that variable, like this:
mypackage/const.go
var (
MyExportedVar string
)
mainpackage/main.go
func init() {
flag.StringVar(&mypackage.MyExportedVar, "flagName", "defaultValue", "usage")
flag.Parse()
}
This way, everybody can access that flag, including that package itself.
Note:
this only works for exported variables.
You can define the flag in that package and call flag.Parse() in func init(), flag.Parse can be called multiple times.
However, if you want to access the flag's value from multiple packages you have to expose it or create an exposed function to check it.
for example:
// pkgA
var A = flag.Bool("a", false, "why a?")
func init() {
flag.Parse()
}
// main package
func main() {
flag.Parse()
if *pkgA.A {
// stuff
}
}
Also you can use FlagSet.Parse(os.Args) if you want to reparse the args.
When you parse your flags, parse them into global variables which start with an initial Capital so they are public, eg
package main
var Species = flag.String("species", "gopher", "the species we are studying")
func main() {
flag.Parse()
}
Then in your other package you can refer to them as
package other
import "/path/to/package/main"
func Whatever() {
fmt.Println(main.Species)
}

Shorten imported variable exports in Go / Golang?

if I have
// types.go
type S string
func (s *S) Lower() *S {
*s = S(strings.ToLower(string(*s)))
return s
}
`
// in another file
import "u/types"
func main() {
s := types.S("asdf")
if s == "asdf" {
s.Lower()
}
}
Is there a way to shorten types.S("asdf") to just S("asdf")?
Is there a way to lowercase method calls from other files? e.g. s.Lower() => s.lower()?
It's not recommended for most cases but you can do import . "u/types" and all then skip the types prefix. . will import all the public symbols into your package for you allowing you to call them as if they were local to your package.
Not as long as that type is in a different package from where you're using it, without using dot-imports.
Yes, if the other file is still in the same package. Otherwise, no, because then the function won't be exported (visible to other packages). This is Go convention.

Resources