dlv debug fail due to undefined object in same package - go

I filed a bug for this over at the delve site.
So, to explain what's going on. I have 2 files in the same package, main.go and common.go. In main.go, it uses some structure from common.go and when i run
dlv debug --listen=:2345 --headless --api-version=2 --log main.go
it fails with 'undefined: NewSimpleStruct' and i am not sure what i am doing wrong.
Here's what the Go files contain,
//main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("HELLO WORLD!")
segasaturn := NewSimpleStruct("SS", 69)
segasaturn.WhoAmI()
fmt.Println("BYE WORLD!")
}
//common.go
package main
import "fmt"
type simpleStruct struct {
name string
id int
}
func NewSimpleStruct(name string, id int) *simpleStruct {
return &simpleStruct{name, id}
}
func (ss *simpleStruct) WhoAmI() {
fmt.Printf("name: %s, id: %d\n", ss.name, ss.id)
}

You did not list the second source file common.go by name.
So try:
dlv debug --listen=:2345 --headless --api-version=2 --log main.go common.go

A common error, and it's not delve's fault; note that you also can't go build main.go here.
You need to do go build . or go build main.go common.go.
Similarly just put all the files or a dot(.) instead of main.go to include all the .go files in the directory
dlv debug --listen=:2345 --headless --api-version=2 --log .

Related

Why `go test` complains undefined _test

I am new to Go. Why go test complains about the undefined test, while go test countdown_test.go main.go is fine?
❯ go test
# main.test
/var/folders/1z/p_x3q6b53mdf7_536x8_8h2h0000gn/T/go-build2418758029/b001/_testmain.go:13:2: cannot import "main"
/var/folders/1z/p_x3q6b53mdf7_536x8_8h2h0000gn/T/go-build2418758029/b001/_testmain.go:21:20: undefined: _test
FAIL main [build failed]
In the directory where I run the command has three files,
main.go:
package main
import (
"bytes"
"fmt"
)
func Countdown(out *bytes.Buffer) {
fmt.Fprint(out, "3")
}
countdown_test.go:
package main
import (
"bytes"
"testing"
)
func TestCountdown(t *testing.T) {
buffer := &bytes.Buffer{}
Countdown(buffer)
got := buffer.String()
want := "3"
if got != want {
t.Errorf("got %q want %q", got, want)
}
}
go.mod:
module main
go 1.17
Passed after changing the module name in go.mod file to:
module Countdown
go 1.17
Before change:
PS D:\##\##\##> go test
# main.test
C:\##\##\AppData\Local\Temp\go-build2311367811\b001\_testmain.go:13:2: cannot import "main"
C:\##\##\AppData\Local\Temp\go-build2311367811\b001\_testmain.go:21:20: undefined: _test
FAIL main [build failed]
After changing the module name:
PS D:\##\##\##> go test
PASS
ok Countdown 0.037s
Please check this refrence.
I will quote the important thing form it:
Even if you’re not at first intending to make your module available for use from other code, using its repository path is a best practice that will help you avoid having to rename the module if you publish it later.

Go run/build cannot find source files

I am trying to run a simple hello world style program that imports a print function from a separate custom package but Go is unable to find it despite teh correct $GOPATH etc being set.
What is missing that will make teh file be picked up?
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ echo $GOPATH
/home/etherk1ll/Development/GoWorkSpace/
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ pwd
/home/etherk1ll/Development/GoWorkSpace/src/sonarparser
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ ls
jsonparser.go main.go
etherk1ll#ubuntu:~/Development/GoWorkSpace/src/sonarparser$ go run main.go
main.go:5:2: cannot find package "sonarparser/jsonparser" in any of:
/usr/local/go/src/sonarparser/jsonparser (from $GOROOT)
/home/etherk1ll/Development/GoWorkSpace/src/sonarparser/jsonparser (from $GOPATH)
main.go
package main
import (
"fmt"
"jsonparser"
)
func main() {
fmt.Println("Hello world 1")
fmt.Println(jsonparser.HelloTwo)
}
jsonparser.go
package jsonparser
import "fmt"
func HelloTwo() {
fmt.Println("Hello world 2")
}
Because jsonparser.go and main.go are in the same package, Go requires those files to have the same package name. And because you defined the main function for the execution, the package must be "main".
Step 1: So you should rename jsonparser.go's package to main.
// jsonparser.go
package main
import "fmt"
func HelloTwo() {
fmt.Println("Hello world 2")
}
Step 2: You need to update main.go file to correct the import path:
// main.go
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello world 1")
HelloTwo()
}
Step 3: Then you run the following command (you must include all necessary files in the command)
go run main.go jsonparser.go

Go public struct in another file

I'm very new with GO and don't understand some basics - so I'm really don't know how to ask ask google about it. So
I have a project with 2 files, both in package main - the root of src. One file is main.go
package main
var (
node * NodeDTO
)
func main() {
node = &NodeDTO{ID: 1}
}
And another is dto.go with
package main
type NodeDTO struct {
ID int
}
So main.go tells me - "undefined: NodeDTO".
But if I create a dir dto near of main.go and use my NodeDTO from there like
package main
import "another_tcp_server/dto"
var (
node * dto.NodeDTO
)
func main() {
node = &dto.NodeDTO{ID: 1}
}
It's ok. Please tell me why this happen?
You appear to have:
$ ls
dto.go main.go
$ cat main.go
package main
var (
node * NodeDTO
)
func main() {
node = &NodeDTO{ID: 1}
}
$ cat dto.go
package main
type NodeDTO struct {
ID int
}
$
and you appear to run:
$ go run main.go
# command-line-arguments
./main.go:4:12: undefined: NodeDTO
./main.go:8:13: undefined: NodeDTO
$
The help for go run says, amongst other things:
$ go help run
usage: go run [build flags] [-exec xprog] package [arguments...]
Run compiles and runs the named main Go package.
Typically the package is specified as a list of .go source files,
but it may also be an import path, file system path, or pattern
matching a single known package, as in 'go run .' or 'go run my/cmd'.
You used a list of .go source files: go run main.go. You listed one file. You have two files: main.go and dto.go.
Use a complete list of .go source files:
$ go run main.go dto.go
$

My main.go file cannot see other files

I need some help understanding what is wrong with my file layout in a simple web application.
$GOPATH/src/example.com/myweb
I then have 2 files:
$GOPATH/src/example.com/myweb/main.go
$GOPATH/src/example.com/myweb/api.go
Both files have:
package main
The api.go file looks like:
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"time"
)
type API struct {
URI string
Token string
Secret string
client *http.Client
}
...
My main.go file looks like:
package main
import (
"github.com/gorilla/mux"
"html/template"
"net/http"
)
var (
templates = template.Must(template.ParseFiles("views/home.html", "views/history.html", "views/incident.html"))
api = API{
URI: "http://localhost:3000",
Token: "abc",
Secret: "123",
}
)
func renderTemplate(w http.ResponseWriter, tmpl string, hp *HomePage) {
..
..
}
func WelcomeHandler(w http.ResponseWriter, r *http.Request) {
..
..
}
func main() {
r := mux.NewRouter()
r.HandleFunc("/", WelcomeHandler)
r.PathPrefix("/assets/").Handler(
http.StripPrefix("/assets/", http.FileServer(http.Dir("assets/"))))
http.ListenAndServe(":9000", r)
}
In the code I excluded, I basically use structs that are defined in my api.go file, and I get this error when doing:
go run main.go
# command-line-arguments
./main.go:16: undefined: API
./main.go:23: undefined: User
What exactly am I doing wrong here?
I tried changing the package name in api.go to myweb but that didn't help.
Am I suppose to use the package name myweb? Is just 1 file suppose to have main?
You're compiling only the main.go file. You should use:
go run main.go api.go
Or:
go run *.go
If you're writing a complex application, you might add everything to packages in subdirectories and have a single main.go file. For instance, etcd has an etcdmain subdirectory/package along with other subdirectories/packages. Something like:
/alarm
/auth
/cmd
/etcdmain
...
And the main.go file is simply:
package main
import "github.com/coreos/etcd/etcdmain"
func main() {
etcdmain.Main()
}
You are using golang workspace project, which is good for the structure for your application and it also standardize.
When we use the golang workspace, you can not run single go file. You need to call go build / go install.
Install
go install example.com/myweb
The command above will compile your main package on example.com/myweb. And the myweb executable binary will be placed on the GOPATH/bin. And you can run it manually.
Build
go build example.com/myweb
The command is similar to go install but the binary executable file will be placed on the current directory when you call the command, instead of on GOPATH/bin (unless your current directory is GOPATH/bin).
For more information please check this link.

How to call function from another file in Go

I want to call function from another file in Go. Can any one help?
test1.go
package main
func main() {
demo()
}
test2.go
package main
import "fmt"
func main() {
}
func demo() {
fmt.Println("HI")
}
How to call demo in test2 from test1?
You can't have more than one main in your package.
More generally, you can't have more than one function with a given name in a package.
Remove the main in test2.go and compile the application. The demo function will be visible from test1.go.
Go Lang by default builds/runs only the mentioned file. To Link all files you need to specify the name of all files while running.
Run either of below two commands:
$go run test1.go test2.go. //order of file doesn't matter
$go run *.go
You should do similar thing, if you want to build them.
I was looking for the same thing. To answer your question "How to call demo in test2 from test1?", here is the way I did it. Run this code with go run test1.go command. Change the current_folder to folder where test1.go is.
test1.go
package main
import (
L "./lib"
)
func main() {
L.Demo()
}
lib\test2.go
Put test2.go file in subfolder lib
package lib
import "fmt"
// This func must be Exported, Capitalized, and comment added.
func Demo() {
fmt.Println("HI")
}
A functional, objective, simple quick example:
main.go
package main
import "pathToProject/controllers"
func main() {
controllers.Test()
}
control.go
package controllers
func Test() {
// Do Something
}
Don't ever forget: Visible External Functions, Variables and Methods starts with Capital Letter.
i.e:
func test() {
// I am not Visible outside the file
}
func Test() {
// I am VISIBLE OUTSIDE the FILE
}
If you just run go run test1.go and that file has a reference to a function in another file within the same package, it will error because you didn't tell Go to run the whole package, you told it to only run that one file.
You can tell go to run as a whole package by grouping the files as a package in the run commaned in several ways. Here are some examples (if your terminal is in the directory of your package):
go run ./
OR
go run test1.go test2.go
OR
go run *.go
You can expect the same behavior using the build command, and after running the executable created will run as a grouped package, where the files know about eachothers functions, etc. Example:
go build ./
OR
go build test1.go test2.go
OR
go build *.go
And then afterward simply calling the executable from the command line will give you a similar output to using the run command when you ran all the files together as a whole package. Ex:
./test1
Or whatever your executable filename happens to be called when it was created.
Folder Structure
duplicate
|
|--duplicate_main.go
|
|--countLines.go
|
|--abc.txt
duplicate_main.go
package main
import (
"fmt"
"os"
)
func main() {
counts := make(map[string]int)
files := os.Args[1:]
if len(files) == 0 {
countLines(os.Stdin, counts)
} else {
for _, arg := range files {
f, err := os.Open(arg)
if err != nil {
fmt.Fprintf(os.Stderr, "dup2: %v\n", err)
continue
}
countLines(f, counts)
f.Close()
}
}
for line, n := range counts {
if n > 1 {
fmt.Printf("%d\t%s\n", n, line)
}
}
}
countLines.go
package main
import (
"bufio"
"os"
)
func countLines(f *os.File, counts map[string]int) {
input := bufio.NewScanner(f)
for input.Scan() {
counts[input.Text()]++
}
}
go run ch1_dup2.go countLines.go abc.txt
go run *.go abc.txt
go build ./
go build ch1_dup2.go countLines.go
go build *.go
You can import functions from another file by declaring the other file as a module. Keep both the files in the same project folder.
The first file test1.go should look like this:
package main
func main() {
demo()
}
From the second file remove the main function because only one main function can exist in a package. The second file, test2.go should look like below:
package main
import "fmt"
func demo() {
fmt.Println("HI")
}
Now from any terminal with the project directory set as the working directory run the command:
go mod init myproject.
This would create a file called go.mod in the project directory. The contents of this mod file might look like the below:
module myproject
go 1.16
Now from the terminal simply run the command go run .! The demo function would be executed from the first file as desired !!
as a stupid person who didn't find out what is going on with go module
should say :
create your main.go
in the same directory write this in your terminal
go mod init "your module name"
create a new directory and go inside it
create a new .go file and write the directory's name as package name
write any function you want ; just notice your function must starts with capital letter
back to main.go and
import "your module name / the name of your new directory"
finally what you need is writing the name of package and your function name after it
"the name of your new dirctory" + . + YourFunction()
and write this in terminal
go run .
you can write go run main.go instead.
sometimes you don't want to create a directory and want to create new .go file in the same directory, in this situation you need to be aware of, it doesn't matter to start your function with capital letter or not and you should run all .go files
go run *.go
because
go run main.go
doesn't work.
Let me try.
Firstly
at the root directory, you can run go mod init mymodule (note: mymodule is just an example name, changes it to what you use)
and maybe you need to run go mod tidy after that.
Folder structure will be like this
.
├── go.mod
├── calculator
│ └── calculator.go
└── main.go
for ./calculator/calculator.go
package calculator
func Sum(a, b int) int {
return a + b
}
Secondly
you can import calculator package and used function Sum (note that function will have Capitalize naming) in main.go like this
for ./main.go
package main
import (
"fmt"
"mymodule/calculator"
)
func main() {
result := calculator.Sum(1, 2)
fmt.Println(result)
}
After that
you can run this command at root directory.
go run main.go
Result will return 3 at console.
Bonus: for ./go.mod
module mymodule
go 1.19
ps. This is my first answer ever. I hope this help.

Resources