modifying imported functions in go - 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.

Related

Golang in vscode: auto-import package

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.

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

cgo doesn't export functions in imported packages

I'm trying to build existed Go package into C shared library and header using CGO.
I built the package with -buildmode c-shared as documented.
-buildmode=c-shared
Build the listed main package, plus all packages it imports,
into a C shared library. The only callable symbols will
be those functions exported using a cgo //export comment.
Requires exactly one main package to be listed
And used //export Func to expose functions as C symbols.
All //export functions in main package are exported properly. However when I moved those functions to sub-package (with //export), those functions are not exported. I imported the sub-package in main package, too.
Here's my code.
main.go
package main
import "C"
import (
"fmt"
_ "github.com/onosolutions/archanan-cgo/c"
"math/rand"
)
// FuncInMain generates a random integer.
//export FuncInMain
func FuncInMain(max C.int) C.int {
return C.int(rand.Intn(int(max)))
}
func main() {
fmt.Printf("Hello World %d!\n", int(FuncInMain(256)))
}
c/c.go
package c
import "C"
import (
"math/rand"
)
// FuncInSubPackage generates a random integer.
//export FuncInSubPackage
func FuncInSubPackage(max C.int) C.int {
return C.int(rand.Intn(int(max)))
}
Then only FuncInMain is exported.
I read through CGO documentation, but there's nothing saying about exporting in sub-packages. The only clue I got is through go help buildmode, but it said that all imported sub-packages will be compiled. I'm not sure whether it isn't supported or I missed some configurations.
I'd love to achieve that to be able to modularize //export functions.
Both of them have own C.type, so as far as I know, there's no way to import function with C.type but using linking.
I didn't tried, but give it a chance:
import _ "unsafe"
//go:linkname FuncInSubPackage c.FuncInSubPackage
//export FuncInSubPackage
func FuncInSubPackage(max C.int) C.int

Call a function from another package in Go

I have two files main.go which is under package main, and another file with some functions in the package called functions.
My question is: How can I call a function from package main?
File 1: main.go (located in MyProj/main.go)
package main
import "fmt"
import "functions" // I dont have problem creating the reference here
func main(){
c:= functions.getValue() // <---- this is I want to do
}
File 2: functions.go (located in MyProj/functions/functions.go)
package functions
func getValue() string{
return "Hello from this another package"
}
You import the package by its import path, and reference all its exported symbols (those starting with a capital letter) through the package name, like so:
import "MyProj/functions"
functions.GetValue()
You should prefix your import in main.go with: MyProj, because, the directory the code resides in is a package name by default in Go whether you're calling it main or not. It will be named as MyProj.
package main just denotes that this file has an executable command which contains func main(). Then, you can run this code as: go run main.go. See here for more info.
You should rename your func getValue() in functions package to func GetValue(), because, only that way the func will be visible to other packages. See here for more info.
File 1: main.go (located in MyProj/main.go)
package main
import (
"fmt"
"MyProj/functions"
)
func main(){
fmt.Println(functions.GetValue())
}
File 2: functions.go (located in MyProj/functions/functions.go)
package functions
// `getValue` should be `GetValue` to be exposed to other packages.
// It should start with a capital letter.
func GetValue() string{
return "Hello from this another package"
}
Export function getValue by making 1st character of function name capital, GetValue
you can write
import(
functions "./functions"
)
func main(){
c:= functions.getValue() <-
}
If you write in gopath write this import functions "MyProj/functions" or if you are working with Docker
In Go packages, all identifiers will be exported to other packages if the first letter of the identifier name starts with an uppercase letter.
=> change getValue() to GetValue()
you need to create a go.mod file in the root directory of your project: go mod init module_name
the name of exposed function should start with capital letter
import(
"module_name/functions"
)
func main(){
functions.SomeFunction()
}

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