Golang in vscode: auto-import package - go

Imagine I want to use strconv.Atoi, but I am lazy, and want to import it automatically.
package main
import (
"fmt"
)
func main() {
i, _ := Atoi|("123")
fmt.Println(i)
}
The pipe sign (|) shows where my cursor is
In PyCharm I was able to automatically import the matching function via alt+ENTER.
Is there a way that vscode changes above code to this one:
package main
import (
"fmt"
"strconv"
)
func main() {
i, _ := strconv.Atoi("123")
fmt.Println(i)
}

VSCode won't guess which package Atoi() is from, but if you tell it, the import will be added automatically.
So just type
i, _ := strconv.Atoi("123")
And hit CTRL+S to save, and the import will be added automatically.
You may also press CTRL+ALT+O which is a shortcut to Organize Imports.
This is a reasonable compromise in Go. As part of API design, exported identifiers are created that read well with the package name. For example the constructor function that creates an MD5 hasher is md5.New() (and not for example md5.NewMD5()), the one that creates an SHA1 hasher is sha1.New(). Just entering New() it's often too verbose, and giving the package name is required to give context to what you refer to.

Related

modifying imported functions in go

I could override the builtin print() function's behavior by defining another print() in scope, as in https://play.golang.org/p/Y2ly31oXU67
Is it possible in go to alter the behavior on-the-fly of an imported function, say fmt.Println()?
If you want to 'alter' a builtin function, look at the very fine monkey patch utility https://github.com/bouk/monkey (And pay attention to the warnings, it's only really useful in test functions, and I for one reject any prod code that imports that package)
Import a different package with name "fmt" and implement whatever functions you need in that package. Here's an example:
File go.mod:
module test
File main.go
package main
import (
"test/fmt"
)
func main() {
fmt.Println("Hello, playground")
}
File fmt/fmt.go:
package fmt
import (
"fmt"
"log"
)
func Println(format string, args ...interface{}) {
msg := fmt.Sprintf(format, args...)
log.Printf(msg)
}
Run it on the playground.
The code in this answer does not modify the imported function as asked in the question.

I can't import "cloud.google.com/go/datastore"

I can't understand why this :/
I tried go get -u ** with every url that I found.
Thanks
Golang:
$ go version
go version go1.13.3 windows/amd64
Source test:
package main
import (
"fmt"
"cloud.google.com/go/datastore"
)
var client *datastore.Client
func main() {
fmt.Println("Work")
}
Error:
$ go run main.go
# google.golang.org/grpc/internal/transport
..\..\..\..\google.golang.org\grpc\internal\transport\http_util.go:270:23: cannot use hf (type "vendor/golang.org/x/net/http2/hpack".HeaderField) as type
"golang.org/x/net/http2/hpack".HeaderField in argument to d.processHeaderField
..\..\..\..\google.golang.org\grpc\internal\transport\http_util.go:675:23: cannot use "golang.org/x/net/http2/hpack".NewDecoder(http2InitHeaderTableSize,
nil) (type *"golang.org/x/net/http2/hpack".Decoder) as type *"vendor/golang.org/x/net/http2/hpack".Decoder in assignment
Go requires you make use of any package that you import. In this case you are importing "cloud.google.com/go/datastore" but not doing anything with it. The global variable that you declared is also not being used. Since it seems you are just trying to test, so I would recommend you do something with it (atleast print it). Like-
package main
import (
"fmt"
"cloud.google.com/go/datastore"
)
var client *datastore.Client
func main() {
fmt.Println(client)
}

Reflect on struct type from reading a .go file

I'm discovering generator (go generate) and I'm trying to generate Validation function for my struct.
The idea is that I don't want my program to use reflect at runtime, I would rather have a generator use reflect to generate the actual method I want to use.
the problem is I can't import my structs in the generator code, the only way I found so far was to read the .go file from the generator and manually parse the types defined there using regex
I've got something like
models/models.go:
package models
//go:generate go run ../generator.go -file models.go
type MyStruct struct {
...
}
generator.go:
package main
func main() {
f, err := ioutil.ReadFile(fileName) // I read filename from the flag provided
...
// I parse f to generate my stuff
}
I would very much prefer to have an introspection package that would take a go code as a string and give me some information about the struct defined there
Or maybe there is a way to import the file that call go:generate to get directly access to the types
There is no need to specify file name , this code does the same :
//go:generate go run ../generator.go -file $GOFILE
With help of text/template package you are needless of parsing the file. A very simple example would be something like this. This will give you the clue :
package main
import (
"flag"
"os"
"text/template"
)
//go:generate go run main.go -name=A
//go:generate go run main.go -name=B
//go:generate go run main.go -name=C
var name = flag.String("name", "test", "name of struct")
var code = `
package main
type Struct{{.}} struct {}
func (s *Struct{{.}} ) Vailadte() bool {
return true
}
`
func main() {
flag.Parse()
file, _ := os.Create(*name + ".go")
defer file.Close()
tmpl, _ := template.New("test").Parse(code)
tmpl.Execute(file, *name)
}
Maybe you can utilize go/parser and go/ast in your generator.

Is it possible don't specify package name?

Here is an example of my code:
package main
import (
"./bio"
)
func main() {
bio.PeptideEncoding(genome, codonTable)
}
Is it possible to use functions from my paxkage (bio) without specifying package name:
func main() {
PeptideEncoding(genome, codonTable)
}
?
You could use as an import declaration like:
. "./bio"
If an explicit period (.) appears instead of a name, all the package's exported identifiers declared in that package's package block will be declared in the importing source file's file block and must be accessed without a qualifier.
That is what a testing framework like govey does:
package package_name
import (
"testing"
. "github.com/smartystreets/goconvey/convey"
)
func TestIntegerStuff(t *testing.T) {
Convey("Given some integer with a starting value", t, func() {
x := 1
Convey("When the integer is incremented", func() {
x++
Convey("The value should be greater by one", func() {
So(x, ShouldEqual, 2)
})
})
})
}
You don't need to use convey.So(), or convey.Convey() because of the import starting with a '.'.
Don't abuse it though, since, as twotwotwo comments, The style guide discourages it outside of tests.
Except for this one case, do not use import . in your programs.
It makes the programs much harder to read because it is unclear whether a name like Quux is a top-level identifier in the current package or in an imported package.
That is why I mentioned a testing framework using this technique.
As commented by Simon Whitehead, using relative import is not generally considered as the best practice (see for instance "Go language package structure").
You should also import the package via the GOPATH instead of relatively, as show in "Import and not used error".

Package selection in Go

I'm trying to write an application to pull status from a database, but I seem to be getting stuck on a really basic principle of the language. I have the program written, but it doesn't compile due to the error use of package time not in selector.
A really basic example (from play.golang.org's own test environment)
package main
import (
"fmt"
"time"
)
func main() {
s_str := time.Now()
fmt.Println( printT(s_str) )
}
func printT(t time) time {
return t.Add(100)
}
Unfortunately, I've found documentation and helpdocs online a bit wanting. My understanding is that the import statement should include the library for the entire program like in C++ correct?
You have to prefix the imported types or variables with the name you gave to the package in the import (here you use the default name, that is "time"). That's what you did for the function Now but you have to do it also for the types.
So the type isn't time but time.Time (that is : the type Time that is declared in the package you import with the name "time").
Change your function to
func printT(t time.Time) time.Time {
return t.Add(100)
}
And for your second question : No, the import statement doesn't include the library for the entire program but only for the current file.

Resources