Method that is present being shown as undefined golang - go

I am trying to call a method from a different directory but getting an error saying that the method is not present. I have the method present with the first letter Uppercase.
I have the following directory structure
[laptop#laptop src]$ tree
.
├── hello
│   ├── hello.go
├── remote_method
│   └── remoteMethod.go
My main is in hello.go and tries to call a function from the remote_method package
package main
import
(
"remote_method"
)
func main() {
mm := remote_method.NewObject()
mm.MethodCall()
}
The remoteMethod.go has the following contents
package remote_method
import (
.....
)
type DeclaredType struct {
randomMap (map[string][](chan int))
}
func NewObject() DeclaredType {
var randomMap (map[string][](chan int))
m := DeclaredType{randomMap}
return m
}
func MethodCall(m DeclaredType, param1 string, param2 string, param3 string, param4 string) {
// Code to be run
}
I get the error
mm.MethodCall undefined (type remote_method.DeclaredType has no field or method MethodCall)
Can someone help me in finding why the method is not visible or any possible ways I could find that.
TIA

Register MethodCall() as a receiver in DeclaredType.
remote_method.go
package remote_method
import (
.....
)
type DeclaredType struct {
randomMap (map[string][](chan int))
}
func NewObject() DeclaredType {
var randomMap (map[string][](chan int))
m := DeclaredType{randomMap}
return m
}
func (d DeclaredType) MethodCall(m DeclaredType, param1 string, param2 string, param3 string, param4 string) {
// Code to be run
}

Related

passing map between packages in golang

In golang, I know that map is passed between functions in the form of reference, but I encountered a strange situation today. The running result of the code is not what I imagined. I simplified it into the following lines of code.
.
├── go.mod
├── main.go
├── packageA
│   └── a.go
└── packageB
└── b.go
main.go file
package main
import (
"gostudy/packageA"
"gostudy/packageB"
)
func main() {
packageB.UseMap(packageA.M, packageA.InitMap)
}
a.go
package packageA
var M map[string]string
func InitMap() {
M = make(map[string]string)
M["hello"] = "go"
}
b.go
package packageB
import "fmt"
func UseMap(m map[string]string, callback func()) {
callback()
fmt.Println(m)
}
As you can see, there is only one variable globally declared in the a.go file. I thought the above program should output map[hello:go], but it actually outputs an empty map[]. I'm very confused about this and hope to get an answer.
You're passing the old value of the map as a parameter, before you invoke the function to replace it with a new version of the map.
Let's say packageA.M contains the value map[string]string{"foo": "bar"}. The main() function reads the variable and gets a reference to this map, and passes it and the function to packageB.UseMap().
Inside packageB.UseMap(), your code calls packageA.InitMap() via the callback. This does not modify the existing map; instead, it creates a new map, assigns it to the global variable, and populates it. Anything that had a copy of the old map is unaffected, and the code you show doesn't re-read the value of packageA.M.
I'd recommend dispensing with the global variable entirely: it can make the code hard to test and there are potential problems once you start using goroutines. Just have your setup function return the new map.
package packageA
func InitMap() map[string]string {
return map[string]string{"hello": "go"}
}
package packageB
func UseMap(callback func() map[string]string) {
m := callback()
fmt.Println(m)
}
package main
import "packageA"
import "packageB"
func main() {
packageB.UseMap(packageA.InitMap)
}
Just as a side note to the accepted anwer, if you take a look at this:
// ...
import (
"reflect"
"fmt"
)
// ... other functions
// I defined all of the functions in a single paackage, so I can access them both here
func UseMap(m map[string]string, callback func()) {
fmt.Println(reflect.ValueOf(m).Pointer() == reflect.ValueOf(M).Pointer()) // prints true, they have the same reference
callback()
// inside callback, M global variable takes a whole new reference
// when "M = make(...)"
// and then =>
fmt.Println(reflect.ValueOf(m).Pointer() == reflect.ValueOf(M).Pointer()) // prints false
}
If you want to avoid this without changing your apis, you can do this in your package A:
package packageA
var M map[string]string = make(map[string]string)
func InitMap() {
M["hello"] = "go"
}

Modularizing golang package using interfaces

I am learning golang and in the process of trying to wrap my head around interfaces and how to use them for unit testing.
I currently have a main.go which calls another package: packageName that I wrote.
Currently in main.go, I use package like this:
package main
import (
...
./packageName
)
func main () {
var1 := "test"
str1 := packageName.Func1(var1)
var2 := "sample"
str2 := packageName.Func2(var2)
}
and packageName is:
package packageName
import (
"os"
"net/http"
)
func Func1 (str string) string {
resp,err := http.get("www.something.com")
return resp.string() // or something along these lines
}
func Func2 (str string) string {
sampleFile, sampleFileErr := os.OpenFile(str, os.O_CREATE, 0600)
return "done"
}
After reading about testing and interfaces, it seems like I have to rewrite everything using interfaces so it can be unit tested (more modular).
My question, is how do I do this properly. Do I put all external library calls into one interface, and then make all functions in the package part of one struct?
example:
package packageName
import (
"os"
"net/http"
)
type External interface {
urlGet(string) (*http.Response, error)
OpenFile(string, int, os.FileMode) (*os.File, error)
}
func New() ExternalSt {
return ExternalSt{}
}
struct ExternalSt struct {}
func (ExternalSt) urlGet(str string) *http.Response {
return http.get(str)
}
func (ExternalSt) OpenFile (str string, flags int, perms os.FileMode) (*os.File, error) {
return os.OpenFile(str, flags, perms)
}
func (e ExternalSt) Func1 (str string) string {
resp,err := e.urlGet("www.something.com")
// do some other stuff
return resp.string() // or something along these lines
}
func (e ExternalSt) Func2 (str string) string {
sampleFile, sampleFileErr := e.OpenFile(str, os.O_CREATE, 0600)
// do some other stuff
return "done"
}
and then main would be:
package main
import (
...
./packageName
)
func main () {
test := packageName.New()
var1 := "test"
str1 := test.Func1(var1)
var2 := "sample"
str2 := test.Func2(var2)
}
With the above implementation I don't even need the interface, but i'm guessing it would come in handy when Im doing unit tests and need to implement my own mock functions under a test interface to call during testing.
OR
should I create an interface with all the external functions, but pass the new instance I create into the functions as a parameter similar to here. Ex:
package main
import (
...
./packageName
)
func main () {
var test packageName.External
var1 := "test"
str1 := packageName.Func1(test, var1)
var2 := "sample"
str2 := packageName.Func2(test, var2)
}
and the package:
package packageName
import (
"os"
"net/http"
)
type External interface {
urlGet(string) (*http.Response, error)
OpenFile(string, int, os.FileMode) (*os.File, error)
}
func New() ExternalSt {
return ExternalSt{}
}
struct ExternalSt struct {}
func (ExternalSt) urlGet(str string) *http.Response {
return http.get(str)
}
func (ExternalSt) OpenFile (str string, flags int, perms os.FileMode) (*os.File, error) {
return os.OpenFile(str, flags, perms)
}
func Func1 (e External, str string) string {
resp,err := e.urlGet("www.something.com")
// do some other stuff
return resp.string() // or something along these lines
}
func Func2 (e External, str string) string {
sampleFile, sampleFileErr := e.OpenFile(str, os.O_CREATE, 0600)
// do some other stuff
return "done"
}
The second option doesn't seem to work very well as I keep getting an error
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation
but I need more of an understanding of interfaces.
Regardless, I cannot seem to understand which of the 2 options are best to go with.
Or are both these options completely wrong.
NOTE: I'm aware the syntax of the above code is incorrect, and will probably not compile, just looking for an approach here.

How to create methods for string type in Golang

I'm planning to create some method extension for the string type.
I need to write all my extension methods into a separate package.
here is my hierarchy.
root
| main.go
| validation
| validate.go
on the main.go I would like to have, "abcd".Required()
main.go
package main
import (
"fmt"
"./validation"
)
func main() {
fmt.Println( "abcd".Required() )
}
validate.go
package validation
func (s string) Required() bool {
if s != "" {
return true
}
return false
}
When I run it, will get an error.
error
cannot define new methods on non-local type string
I found some answers in other questions on StackOverflow but they don't exactly talk about the string type & having the method in a different package file.
In your validate.go create a new type String:
package validation
type String string
func (s String) Required() bool {
return s != ""
}
And then work with validation.String objects in your main:
package main
import (
"fmt"
"./validation"
)
func main() {
fmt.Println(validation.String("abcd").Required())
}
An executable example with it all in the same file here:
https://play.golang.org/p/z_LcTZ6Qvfn

How to use constant across go package

I'm writing my first go code and I'm trying to convince myself what I'm doing is not wrong.
anyway, here the project the tree structure.
.
├── helpers
│   └── common.go
├── logger
│   └── util.go
├── logger_example
└── runner.go
The main file to look over here is logger/util.go which look like this.
package logger
import (
"log"
"os"
)
type Logger struct {
*log.Logger
}
func (l *Logger) Info(v ...interface{}) {
l.SetPrefix("Info: ")
l.Println(v...)
}
func (l *Logger) Error(v ...interface{}) {
l.SetPrefix("Error: ")
l.Println(v...)
}
func (l *Logger) Warn(v ...interface{}) {
l.SetPrefix("Warn: ")
l.Println(v...)
}
func (l *Logger) Debug(v ...interface{}) {
l.SetPrefix("Debug: ")
l.Println(v...)
}
func NewLogger() *Logger {
logger := log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lshortfile)
return &Logger{logger}
}
As you all can see, I'm just setting the prefix to "INFO | WARN | ERROR | DEBUG"
On the main package I have safely created a Logger instance and VOILA it worked.
Only until I decided to add a helpers package and now things do not look the way I wanted.
since the logger.Logger instance created inside main package, I have to pass it reference to every since package function where I want to invoke the logger statement. (see the below example ..)
// dodly_logger/logger/common.go
package helpers
import "dodly_logger/logger"
func Display(dodlyLogger *logger.Logger) {
dodlyLogger.Info("Inside a helper package")
}
The Main package..
package main
import (
logger "dodly_logger/logger"
helpers "dodly_logger/helpers"
)
func main() {
dodlyLogger := logger.NewLogger()
dodlyLogger.Info("INFO MESSAGE")
dodlyLogger.Error("ERROR MESSAGE")
// Ehh, I have to pass the dodlyLogger ..
helpers.Display(dodlyLogger)
}
Ok, now I know my GOLang knowledge is not complete hence I'm hoping people over here can point me how can I write this more clinically wherein I do not have to pass the reference of the logger.Logger to every function for which I need to log.
Create a package level variable with var.
package main
import (
logger "dodly_logger/logger"
helpers "dodly_logger/helpers"
)
var dlogger logger.Logger
func init() {
dlogger = logger.NewLogger()
}
func main() {
dlogger.Info("Starting Main")
a()
}
func a() {
dlogger.Info("in a")
}

Implementing an interface in Go

My project is organized as follows
github.com/achanda/poke
├── cmd
│   └── poke.go
├── scanner.go
├── txt_scanner.go
└── types.go
The files are as follows
# cat scanner.go
package poke
type Scanner interface {
Scan() *ScanResult
}
# cat txt_scanner.go
package poke
type txtScanner struct {
txt string
}
func newTxtScanner(host string) Scanner {
return txtScanner{txt}
}
func (tcpcs txtScanner) Scan() *ScanResult {
// do stuff
return &result
}
Now I am trying to call this in my main package (in poke.go) like this
package main
import "github.com/achanda/poke"
func main() {
var sr poke.Scanner
sr = poke.txtScanner{txt}
sr.Scan()
}
This fails to run with
# command-line-arguments
./poke.go:111: cannot refer to unexported name poke.txtScanner
./poke.go:111: undefined: portscan.txtScanner
What am I doing wrong?
you need to access type or field outside package, so you should export them using first letter upper case:
first you should define your txtScanner and txt string with first upper case letter, otherwise you will see this error too:
.\poke.go:8: implicit assignment of unexported field 'txt' in poke.TxtScanner literal
like this:
type TxtScanner struct {
Txt string
}
also see newTxtScanner(host string) function in this working sample codes:
poke.go:
package main
import "github.com/achanda/poke"
func main() {
s := "test"
var sr poke.Scanner
sr = poke.TxtScanner{s}
sr.Scan()
}
txt_scanner.go:
package poke
type TxtScanner struct {
Txt string
}
func newTxtScanner(host string) Scanner {
return TxtScanner{host}
}
func (tcpcs TxtScanner) Scan() *ScanResult {
// do stuff
result := ScanResult{}
return &result
}
types.go:
package poke
type ScanResult struct {
}
scanner.go:
package poke
type Scanner interface {
Scan() *ScanResult
}

Resources