How to export a name so that it becomes globally accessible? - go

I want to export a function from my package so that I can use it without typing a package name before it, how to do that?
import "mypackage"
func main() {
mypackage.myfunc() <-- that's what I have already
myfunc() <-- that's what I need
}

You can use one of the followings:
import (
. "mypackage" // without a name
mp "my/other/package" // rename
_ "my/totally/diffrent/package" // import a package solely for its side-effects (initialization)
)
Obviously, this pattern is not recommended since it can cause name conflicts with other packages.
Check out the dot imports bulletin

Related

Directory Structure and Import

I do not understand how the package / project directory structure works.
I am following these 2 links enter link description here and enter link description here
My Go workspace is located under /workspace/golang.
My $GOPATH is equal to /workspace/golang
My directory structure is as follow :
/workspace/golang/src/Tutorial/
...tutorial_main.go <- Default 'Hello World' program
...library/
......arithmetic.go
Content of arithmetic.go :
package library
func addNum(a int, b int) int {
return a + b
}
I cd into library folder and ran go build arithmetic
Now, I cannot figure out how to use my arithmetic.go in my tutorial_main.go file.
I tried the following :
import "library"
fmt.Println("Result : ", library.addNum(1,4))
import "Tutorial/library"
fmt.Println("Result : ", library.addNum(1,4))
import "src/Tutorial/library"
fmt.Println("Result : ", library.addNum(1,4))
Neither works.
It keep saying it cannot find library
I don't understand what I am doing wrong.
With your setup, the package import path is:
import "Tutorial/library"
And you should capitalize the names you want to export in the library package so you can access them from other packages.
In general, the import path is the file path of the package (relative to $GOPATH) if it is local, or the remote path of the package, such as github.com/myaccount/package. The simple import names such as import library are reserved for built-in packages. Relative import paths also work, but they are not recommended, i.e. import ./library.
That said, with the module system $GOPATH is no longer used. I recommend you read modules and how you can work outside the $GOPATH.
In Go, your variables and functions that you'd like to export (make available outside your package) need to start with a capital letter.
package library
func privateAddNum(a int, b int) int {
return a + b
}
func PublicAddNum(a int, b int) int {
return a + b
}
privateAddNum is an unexported function and will only be accessible within the library package.
PublicAddNum is an exported function and will be accessible to external packages that import library.

How to properly import a package from sub-directory in Golang?

I am pretty new to Golang and trying to make a simple REST api app work.
Initially, everything was all fine since I had all code in the same directory under the main package.
But, now I am at a stage where I need to start refactoring code into sub-directories and packages. Unfortunately, I have not been able to compile the app successfully.
My GOPATH is set to: ~/.workspace
The current app is at: ~/.workspace/src/gitlab.com/myapp/api-auth
This is how my current code organization is:
Here is my main.go
package main
import (
"net/http"
"os"
"strings"
"github.com/gorilla/context"
"github.com/justinas/alice"
"gopkg.in/mgo.v2"
"gitlab.com/myapp/api-auth/middlewares"
)
func main() {
privateKey := []byte(strings.Replace(os.Getenv("JWT_KEY"), "\\n", "\n", -1))
conn, err := mgo.Dial(os.Getenv("MONGO_CONN"))
if err != nil {
panic(err)
}
defer conn.Close()
conn.SetMode(mgo.Monotonic, true)
ctx := appContext{
conn.DB(os.Getenv("MONGO_DB")),
privateKey,
}
err = ctx.db.C("users").EnsureIndex(mgo.Index{
Key: []string{"username"},
Unique: true,
Background: true,
Sparse: false,
})
if err != nil {
panic(err)
}
commonHandlers := alice.New(LoggingHandler, context.ClearHandler, RecoveryHandler, AcceptHandler, ContentTypeHandler)
router := NewRouter()
router.Post("/users", commonHandlers.Append(BodyParserHandler(UserResource{})).ThenFunc(ctx.userCreationHandler))
router.Post("/sessions", commonHandlers.Append(BodyParserHandler(UserResource{})).ThenFunc(ctx.sessionCreationHandler))
http.ListenAndServe(":8080", router)
}
type appContext struct {
db *mgo.Database
privateKey []byte
}
Here is one of the middleware accept.go (Rest of the middleware are constructed similarly)
package middlewares
import "net/http"
// AcceptHandler ensures proper accept headers in requests
func AcceptHandler(next http.Handler) http.Handler {
fn := func(w http.ResponseWriter, r *http.Request) {
if r.Header.Get("Accept") != "application/vnd.api+json" {
writeError(w, errNotAcceptable)
return
}
next.ServeHTTP(w, r)
}
return http.HandlerFunc(fn)
}
This is the error I get when I run go build from root of my app.
# gitlab.com/utiliti.es/api-auth
./main.go:11: imported and not used: "gitlab.com/myapp/api-auth/middlewares"
./main.go:42: undefined: LoggingHandler
./main.go:42: undefined: RecoveryHandler
./main.go:42: undefined: AcceptHandler
./main.go:42: undefined: ContentTypeHandler
./main.go:45: undefined: BodyParserHandler
./main.go:46: undefined: BodyParserHandler
The Go Programming Language Specification
Qualified identifiers
A qualified identifier is an identifier qualified with a package name
prefix. Both the package name and the identifier must not be blank.
QualifiedIdent = PackageName "." identifier .
A qualified identifier accesses an identifier in a different package,
which must be imported. The identifier must be exported and declared
in the package block of that package.
math.Sin // denotes the Sin function in package math
Import declarations
An import declaration states that the source file containing the declaration depends on functionality of the imported package (§Program
initialization and execution) and enables access to exported
identifiers of that package. The import names an identifier
(PackageName) to be used for access and an ImportPath that specifies
the package to be imported.
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
The PackageName is used in qualified identifiers to access exported identifiers of the package within the importing source file.
It is declared in the file block. If the PackageName is omitted, it
defaults to the identifier specified in the package clause of the
imported package. 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.
The interpretation of the ImportPath is implementation-dependent but it is typically a substring of the full file name of the compiled
package and may be relative to a repository of installed packages.
Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to Unicode's L, M,
N, P, and S general categories (the Graphic characters without spaces)
and may also exclude the characters !"#$%&'()*,:;<=>?[]^`{|} and the
Unicode replacement character U+FFFD.
Assume we have compiled a package containing the package clause package math, which exports function Sin, and installed the compiled
package in the file identified by "lib/math". This table illustrates
how Sin is accessed in files that import the package after the various
types of import declaration.
Import declaration Local name of Sin
import "lib/math" math.Sin
import m "lib/math" m.Sin
import . "lib/math" Sin
An import declaration declares a dependency relation between the importing and imported package. It is illegal for a package to import
itself, directly or indirectly, or to directly import a package
without referring to any of its exported identifiers. To import a
package solely for its side-effects (initialization), use the blank
identifier as explicit package name:
import _ "lib/math"
The error
./main.go:11: imported and not used: "gitlab.com/myapp/api-auth/middlewares"
says that you have no uses of package middlewares in package main, which is true.
The error
./main.go:42: undefined: AcceptHandler
says that you haven't defined AcceptHandler in package main, which is true.
"A qualified identifier is an identifier qualified with a package name prefix. A qualified identifier accesses an identifier in a different package, which must be imported."
For example, in package main, use the qualified identifier middlewares.AcceptHandler, which is a use of import "gitlab.com/myapp/api-auth/middlewares".

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".

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

Error in importing custom packages in Go Lang

I have created a library by the name libfastget which is in the src with my program as
src
|-libfastget
| |-libfastget.go
|
|-MainProgram
|-main.go
and the libfastget exports a funtion fastget as follows
package libfastget
import (
"fmt"
"io"
)
func fastget(urlPtr *string, nPtr *int, outFilePtr *string) download {
.....
return dl
}
When I use the library in my main program
package main
import (
"fmt"
"net/http"
"os"
"libfastget"
"path/filepath"
"strings"
"flag"
"time"
)
func uploadFunc(w http.ResponseWriter, r *http.Request) {
n:=libfastget.fastget(url,4,filename)
}
}
I get the following error upon trying to build with go build
# FServe
./main.go:94: cannot refer to unexported name libfastget.fastget
./main.go:94: undefined: libfastget.fastget
The strange thing is that the library file libfastget.a is present in the pkg folder.
you would need to make your function exportable with an uppercase for its name:
func Fastget(...
Used as:
n:=libfastget.Fastget(url,4,filename)
The spec mentions: "Exported identifiers":
An identifier may be exported to permit access to it from another package. An identifier is exported if both:
the first character of the identifier's name is a Unicode upper case letter (Unicode class "Lu"); and
the identifier is declared in the package block or it is a field name or method name.
All other identifiers are not exported.
to export a function into another package the function identifier must start with a capital letter.
I recently started learning GO Lang (2 days back)
And what I found was you need to setup a workspace folder to make the local packages import into other projects or main.go files. I'm using VS Code editor. Please correct me if Im wrong, but this setup works fine for me.
Inside your bash_profile OR .zshrc file add below lines, update the GOPATH as per your folder path.
export GOPATH=~/projects/GO_PROJECTS
export PATH=$PATH:$GOPATH/bin:$PATH
and this is my sayHello.go file, please note to be able to export a function the func name should start with a CapitalCase SayHello
package utils
import "fmt"
func SayHello() {
fmt.Println("Hello, Ajinkya")
}
and now I am able to import utils package into main.go file
package main
import (
"go_proj1/utils"
)
func main() {
utils.SayHello()
}
set the current directory as GOPATH
or you can use local import as follows
move your main.go to the ../ directory to the libfastget.go.
i mean the files looks like:
src
|-libfastget
| |-libfastget.go
|
|-main.go
import "./libfastget"

Resources