Workflow for Google Cloud Functions with Golang - go

When developing a small Google Cloud Function in Go. I noticed it will throw an error if you have everything in your package main - eg. import "<whatever>" is a program, not an importable package
So the solution is switch it out to its own package, then deploy. If something goes wrong, throw it back into a package main and work on it locally, then switch it back.
Is this the best workflow? The other option i see is possibly making the Cloud Function its own module and importing it into a main.go file.

I was able to create a cli folder in project's top level and then put main.go file using package main and main() function inside it. That allowed me to have separate file cloud_functions.go in root with different package name that has one or more google cloud functions in it.

Related

Unit test does not cover locally imported packages

I am new to golang and trying to understand how i can make this scenario work?
Here is my structure
GOPATH set to /Users/xyz/project
/Users/xyz/project/src/main.go // import calculator and call SUM with two integeres
/Users/xyz/project/src/main_test.go // test function
/Users/xyz/project/src/calculator/sum.go // SUM function (add two integers)
i have a main go file that imports "calculator" which is a local packages. When i run
go test -cover
it only gives the coverage of main but not for the package "calculator" imported by main. i know i can write a test inside calculator and that would do the trick but is there any way possible to get the coverage of locally imported package from main?
Bigger Context - The reason i want to do this is because i have a micro service written in go using gin framework and i want to spin it up as a service and make http calls and further see how the coverage looks like (like component test). I can easily spin it up by writing a main_test go file which starts the service but i am not getting the coverage of the imported packages.
Finally found response here. looks like go has a test binary that can be used
https://www.elastic.co/blog/code-coverage-for-your-golang-system-tests

Using local packages with gb

I'm starting a new project and considering gb as my build tool but it doesn't appear to be integrating very well with vscode...
I've referenced 3rd party dependencies no problem using gb vendor fetch but as for creating local packages, this is proving a little trickier! Am I missing something obvious?
Here's my local src directory:
src
/cmd
/model
calc.go
/server
server.go
The following code compiles and creates a bin\server.exe file successfully but the import path isn't picked up, nor does gocode recognise it
Here's the server code:
package main
import (
"cmd/model" // not a happy reference...
"fmt"
)
func main() {
fmt.Println(model.Add(1, 2))
}
Here's the model code:
package model
func Add(a int, b int) int {
return a + b
}
I've found what appears to be a similar issue on Github (https://github.com/joefitzgerald/go-plus/issues/325) and while nsf's solution sorts out auto-complete (post import), the import statement itself still claims to be searching in the GOROOT and GOPATHs.
Any ideas?
Thanks to an answer from lukehoban here https://github.com/Microsoft/vscode-go/issues/249 I was able to get my environment working.
I simply created a settings.json file under the .vscode directory (which will now have to be checked in) into which I've configured:
{
"go.gopath": "${workspaceRoot}"
}
This makes me feel unclean and it still doesn't provide a way to reference both 3rd party dependencies and local packages together...
Do not try to work against Go, work with Go.
First of all give all your packages fully qualified import paths. Go is designed around global import paths, do not try to force Go into using flat hierarchies or even relative paths.
You can point to your import path repository endpoints either directly or by using Go's remote import path mechanism. BTW, if you happen to run a self-hosted GitLab instance, it supports remote import path meta tags out of the box.
I prefer glide, but maybe the following is possible with gb, too. Certainly something simililar will be possible with the upcoming go dep: You can point to ssh+git endpoints and others using glide's repo stanza. Frankly I have no idea if gb supports an equivalent mechanism, but if it doesn't this is a good reason to reconsider.

Proper folder structure for go packages used by a single go project

I am currently starting with Go and have already dug into the dos and don'ts regarding package naming and workspace folder structure.
Nevertheless, I am not quite sure how to properly organize my code according to the Go paradigm.
Here is my current structure example as it resides in $GOPATH/src:
github.com/myusername/project
|-- main.go
+-- internal
+---- config
|------ config.go
So i have the project called project which uses the config package which, in turn, is specialized in a way that it should only be used by project. Hence, I do not want it under github.com/myusername/config, right?
The question now is, is it "good" to use the internal package structure or should I instead put my project specific packages under github.com/myusername/$pkgname and indicate somehow that it belongs to project (e.g. name it projectconfig)?
If your project produces one single program then the most common structure is the one you mentioned.
If your project produces more than one program the common practice is using a structure like this:
<project>/
cmd/
prog1/
main.go
prog2/
main.go
If your project exposes go code as library for third party consumption the most common structure is using the project's root dir to expose the domain model and API.
<project>/
model.go
api.go
This is for third party code to just import "github.com/user/project" and have the model and api available.
Is common to see second and third options combined.
Also is considered good practice to have packages for encapsulating dependencies usage. E.g. suppose your project uses the elastic search client
<project>/
cmd/
prog1/
main.go
elastic/
impl.go
dao.go
model.go
So in dao.go you define the dao's API and then in elastic/impl.go you (import elastic library, domain modal and) define the implementation of DAO in terms of elastic. Finally you import everything from main.go which produces the actual program.
See this great and short presentation about this issue.

Inherit Controller From Module in Revel Framework

I am trying to use a shared controller from a module in my app, but I'm not really sure how to do it. Here's what I want to do:
I have two revel apps, a frontend and backend app. The frontend app is used to show the user-facing site, and the backend app is for admin stuffs.
I created a special controller to connect to database as per the booking sample.
I want both the frontend and backend app to use the same controller, to minimize redundancy.
From the sample, when you want to have one controller database, it roughly translate to this:
type DBController {
*revel.Controller
}
type App {
DBController
}
This works when I want to have only 1 app, but when I want to share the controller to another app, I can't import DBController to the app.
Things I've Tried
I tried moving DBController to its own package, and then importing that and inherit from it directly:
// in db.go
package controllers
// import and stuffs
type DBController {
*revel.Controller
}
// in app.go
package controllers
import (
dbc "site.com/modules/controllers"
)
type App struct {
dbc.DBController
// *dbc.DBController
}
This gives me a panic error stating that the route is not found:
panic: Route validation error (in /app/path/routes:7):
revel/controller: failed to find controller App
in both inheriting with and without pointer.
I've also tried Revel's module, with the same code, but different directory and importing via config:
// app.conf
modules.dbcontroller=site.com/modules/dbcontroller
And then in app.go:
type App struct {
DBController
}
But it still didn't work with the same error as before. I'm pretty convinced that the right route is by using module, since the documentation said (emphasis mine):
Modules are packages that can be plugged into an application. They allow sharing of controllers, views, assets, and other code between multiple Revel applications or from third-party sources.
A module should have the same layout as a Revel application’s layout. The “hosting” application will merge it in as follows:
Any templates in module/app/views will be added to the Template Loader search path
Any controllers in module/app/controllers will be treated as if they were in your application.
etc..
But I'm not sure how I can share and derive my controller from here.
TL; DR
How do I share controller in Revel so that I can inherit a controller from other module, roughly like:
import dbc "site.com/modules/dbcontroller"
type App struct {
dbc.DBController
}
so that DBController can be used with several revel apps? Thank you very much.
I am not an authority, but I will make a few observations that might help even though I do not have a complete answer for you.
The first thing about your question that struck me is the use of the term "inherit" -- Go does not support inheritance. It does support embedding. I might have written the question subject as "Reuse controller from module in Revel framework.
Second, I wonder if you are trying to reuse a Revel module between two separate Revel applications or if you are trying to reuse code from a module in two separate parts of one Revel application that just happens to have a front end and a back end. A quick read of the reveal framework makes me think modules were designed for the former, not the latter.
Third, I wonder if perhaps you are confusing files with packages. It was not obvious to me when learning Go that one package can span multiple files.. if the same declaration of "package controller" exists in two files such as db.go and app.go, they are still in the same package.

go run: cannot run non-main package

here the simple go application. I am getting "go run: cannot run non-main package" error, if I run following code.
package zsdfsdf
import (
"fmt"
)
func Main() {
fmt.Println("sddddddd")
}
To fix it, I just need to name the package to main. But I don't understand why I need to do that. I should be able to name the package whatever I want.
Another question, I know main function is the entry point of the program, you need it. otherwise it will not work. But I see some codes that didn't have main function still works.
Click on this link, the example at the bottom of the page didn't use package main and main function, and it still works. just curious why.
https://developers.google.com/appengine/docs/go/gettingstarted/usingdatastore
The entry point of each go program is main.main, i.e. a function called main in a package called main. You have to provide such a main package.
GAE is an exception though. They add a main package, containing the main function automatically to your project. Therefore, you are not allowed to write your own.
You need to use the main package, a common error starting with go is to type
package Main
instead of
package main
You need to specify in your app.yaml file what your app access point is. Take a look here. You need to specify:
application: zsdfsdf
Also see from that above link:
"Note: When writing a stand-alone Go program we would place this code
in package main. The Go App Engine Runtime provides a special main
package, so you should put HTTP handler code in a package of your
choice (in this case, hello)."
You are correct that all Go programs need the Main method. But it is provided by Google App Engine. That is why your provided example works. Your example would not work locally (not on GAE).
A Solution to avoid this error is defining entry point somefilename.go file as main package by adding package main as the first line of the entry point
package main
// import statements
import "fmt"
// code below
To avoid the problem you can modify the code as follow
package main
import (
"fmt"
)
func main() {
fmt.Println("sddddddd")
}
rename the package as "main" and rename the function as "main" instead of "Main".

Resources