Problem
I have written some example functions located in a *_test.go file to help clarify context for standalone public functions without issue. The problem on displaying comes when writing example functions for functions tied to a type.
Example
Here's a basic example of what I'm encountering.
Say we have a function in main.go like below:
type Client struct {
user string
ip string
}
func (c *Client) SendNotification(message string) error {
return nil
}
I want to create an example function for such in main_test.go, like below
func ExampleSendNotification() {
//Showoff code here
}
VSCode throws an error for that specific example, saying "ExampleSendNotification refers to unknown identifier: SendNotification". Also, it just does not appear as an example when running the godoc.
I've also tried this format:
func (c *Client) ExampleSendNotification() {
//Showoff code here
}
But then it just removes it as a test in VSCode, and doesn't appear
I found the answer just as I was finishing writing this. Thought I would still post for anybody else.
The trick is writing Example[Type]_[Method], so practically in my example, that would look like:
func ExampleClient_SendNotification() {
//Showoff code here
}
I want to start learning about the fasthttps server from this link https://github.com/valyala/fasthttp but I dont know that how will I implement a small piece of code in this framework. Can anybody tell me that how i will implement a small piece of code in this? example please.
Code I tried
package main
import "fmt"
type MyHandler struct {
foobar string
}
func main() {
// pass bound struct method to fasthttp
myHandler := &MyHandler{
foobar: "foobar",
}
fasthttp.ListenAndServe(":8080", myHandler.HandleFastHTTP)
// pass plain function to fasthttp
fasthttp.ListenAndServe(":8081", fastHTTPHandler)
}
// request handler in net/http style, i.e. method bound to MyHandler struct.
func (h *MyHandler) HandleFastHTTP(ctx *fasthttp.RequestCtx) {
// notice that we may access MyHandler properties here - see h.foobar.
fmt.Fprintf(ctx, "Hello, world! Requested path is %q. Foobar is %q",
ctx.Path(), h.foobar)
}
// request handler in fasthttp style, i.e. just plain function.
func fastHTTPHandler(ctx *fasthttp.RequestCtx) {
fmt.Fprintf(ctx, "Hi there! RequestURI is %q", ctx.RequestURI())
}
Can you please tell me that how I will implement this code.
This code seems to be working. I pasted it to a .go file, added:
import "github.com/valyala/fasthttp"
Then you have to install this package, either by using go get github.com/valyala/fasthttp or by writing a go.mod file if you want to use the new module support.
Then run this file and open localhost:8080 in a browser.
Maybe you have a more concrete question?
As #Volker said in a comment, for newbies it's highly recommended to stick to the standard library - net/http in this case; there are way more examples and code/tutorials you can find by googling, no need to install special packages, etc.
I have an application which needs configuration and I’ve created a configuration struct and I’m entering the configuration as a parameter to the function. The problem is that the configuration struct becomes bigger (like monolith) and bigger and I move the config to different functions in my app and which doesn’t need all the fields, just few of them. My question is if there is better approach to implement it in Go.
After struggling to find good way I’ve found this article (which a bit old but hopefully still relevant) and I wonder how and if I can use it to solve my problem.
Functional options instead of config struct
https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis
I need to inject some configuration properties to my application in
For example for function run (which is entry point ) I need to inject the log level and some other env variable like port host
For function build I need to “inject” the build flavor and build type etc.
Any example for my content will be very helpful
How to structure it in the code ?
How to implement it?
update
I need some E2E example how can I use the functional approach for different configs in the same package and other packages
It sounds like you're looking for an alternative to passing around the same configuration monolith structure to every package and every function. There are many solutions to this problem (more than I'm going to list here), and which one is right for you requires more knowledge of your code and your goals than we have, so it's probably best if you decide. And it sounds like you're wondering whether Dave Cheney's post on functional options provides a solution and how to apply it.
If your application's configuration is static in that it's not likely to change (mutate) through different threads of execution, and you don't need to create multiple instances with different configurations in the same main, then one option is package level variables and package initialization. If you object to exported package variables, you can use unexported package variables and control access via exported functions. Say run and build are two different packages:
// package main
import(
"github.com/profilename/appname/build"
"github.com/profilename/appname/run"
)
func main() {
// do something to get configuration values
build.Initialize(buildFlavor, buildType)
// any post-build-initialize-pre-run-initialize stuff
run.Initialize(logLevel, port, host)
// other processing
build.PreBuild("title") // other build functions may rely on configuration
build.Build()
// other stuff
run.ReadFiles(f1, f2)
run.Validate(preferredBackupPort) // port availability, chance to log.Fatal out
run.Run()
// cleanup
}
// package run
var Host string
var LogLevel, Port int
init() {
Host = `localhost`
Port = 8888
Loglevel = 1
}
func Initialize(logLevel, port int, host string) {
// validation, panic on failure
LogLevel = logLevel
Host = host
Port = port
}
func Run() {
// do something with LogLevel, Host, Port
}
But that doesn't solve the problem addressed in Dave Cheney's post. What if the user is running this without host, port, or buildType (or other configuration variables), because he doesn't need those features? What if the user wants to run multiple instances with different configurations?
Dave's approach is primarily intended for situations where you will not use package-level variables for configuration. Indeed, it is meant to enable several instances of a thing where each instance can have a different configuration. Your optional configuration parameters become a single variadic parameter where the type is a function that modifies a pointer to the thing being configured. For you, that could be
// package run
type Runner struct {
Port int
// rest of runner configuration
}
func NewRunner(options ...func(*Runner)) (runner *Runner, err error) {
// any setup
for _, option := range options {
err = option(runner)
if err != nil {
// do something
}
}
return runner, err
}
// package main
func main() {
// do something to get configuration values
port := func(runner *Runner) {
runner.Port = configuredPort
}
// other configuration if applicable
runner := run.NewRunner(port)
// ...
In a way, Dave's approach appears targeted at packages that will be used as very flexible libraries, and will provide application interfaces that users might wish to create several instances of. It allows for main definitions that launch multiple instances with different configurations. In that post he doesn't go into detail on how to process configuration input in the main or on a configuration package.
Note that the way the port is set in the resulting code above is not very different from this:
// package run
type Runner struct {
Port int
// rest of runner configuration
}
// package main, func main()
runner := new(run.Runner)
runner.Port = configuredPort
which is more traditional, probably easier for most developers to read and understand, and a perfectly fine approach if it suits your needs. (And you could make runner.port unexported and add a func (r *Runner) SetPort(p int) { r.port = p } method if you wanted.) It is also a design that has the potential, depending on implementation, to deal with mutating configuration, multiple threads of execution (you'll need channels or the sync package to deal with mutation there), and multiple instances.
Where the function options design Dave proposed becomes much more powerful than that approach is when you have many more statements related to the setting of the option that you want to place in main rather than in run -- those will make up the function body.
UPDATE Here's a runnable example using Dave's functional options approach, in two files. Be sure to update the import path to match wherever you put the run package.
Package run:
package run
import(
"fmt"
"log"
)
const(
DefaultPort = 8888
DefaultHost = `localhost`
DefaultLogLevel = 1
)
type Runner struct {
Port int
Host string
LogLevel int
}
func NewRunner(options ...func(*Runner) error) (runner *Runner) {
// any setup
// set defaults
runner = &Runner{DefaultPort, DefaultHost, DefaultLogLevel}
for _, option := range options {
err := option(runner)
if err != nil {
log.Fatalf("Failed to set NewRunner option: %s\n", err)
}
}
return runner
}
func (r *Runner) Run() {
fmt.Println(r)
}
func (r *Runner) String() string {
return fmt.Sprintf("Runner Configuration:\n%16s %22d\n%16s %22s\n%16s %22d",
`Port`, r.Port, `Host`, r.Host, `LogLevel`, r.LogLevel)
}
Package main:
package main
import(
"errors"
"flag"
"github.com/jrefior/run" // update this path for your filesystem
)
func main() {
// do something to get configuration values
portFlag := flag.Int("p", 0, "Override default listen port")
logLevelFlag := flag.Int("l", 0, "Override default log level")
flag.Parse()
// put your runner options here
runnerOpts := make([]func(*run.Runner) error, 0)
// with flags, we're not sure if port was set by flag, so test
if *portFlag > 0 {
runnerOpts = append(runnerOpts, func(runner *run.Runner) error {
if *portFlag < 1024 {
return errors.New("Ports below 1024 are privileged")
}
runner.Port = *portFlag
return nil
})
}
if *logLevelFlag > 0 {
runnerOpts = append(runnerOpts, func(runner *run.Runner) error {
if *logLevelFlag > 8 {
return errors.New("The maximum log level is 8")
}
runner.LogLevel = *logLevelFlag
return nil
})
}
// other configuration if applicable
runner := run.NewRunner(runnerOpts...)
runner.Run()
}
Example usage:
$ ./program -p 8987
Runner Configuration:
Port 8987
Host localhost
LogLevel 1
I use this to define per package Config Structs which are easier to manage and are loaded at the app start.
Define your config struct like this
type Config struct {
Conf1 package1.Configuration `group:"conf1" namespace:"conf1"`
Conf2 package2.Configuration `group:"conf2" namespace:"conf2"`
Conf3 Config3 `group:"conf3" namespace:"conf3"`
GeneralSetting string `long:"Setting" description:"setting" env:"SETTING" required:"true"`
}
type Config3 struct {
setting string
}
And use "github.com/jessevdk/go-flags" to pass either --config3.setting=stringValue cmd arguments, or ENV variables export CONFIG3_SETTING=stringValue:
type Configuration interface {}
const DefaultFlags flags.Options = flags.HelpFlag | flags.PassDoubleDash
func Parse(cfg Configuration) []string {
args, _ := flags.NewParser(cfg, DefaultFlags).Parse()
return args
}
And your main should look something like this:
func main() {
// Parse the configuration.
var cfg Config
Parse(&cfg)
service := NewService(cfg.Conf3.Setting)
}
I'm trying to use go-errors to include stack traces with errors I generate. I have a custom HttpError type that I also want to include stack traces. My initial thought was to do this with an embed, but I can't seem to embed it since the name of the class (Error) is the same as the name of one of the methods.
package netutil
import (
"github.com/go-errors/errors"
)
type HttpError struct {
status int
*errors.Error
}
func (h *HttpError) Error() string {
return "Failed"
}
func NewHttpError(status int, message string) *HttpError {
return &HttpError{
status,
errors.New(message),
}
}
I receive the following error:
tmp_error.go:12: type HttpError has both field and method named Error
Any suggestions?
Why not just name this inner error with something appropriate like inner-error or stack-trace?
type HttpError struct {
status int
StackTace *errors.Error
}
Seems to be fairly common practice in classes used for error handling in other languages/frameworks like .NET and Java.
Another option would be to concatenate your custom message with the inner error using fmt.Sprintf at the time you create the error, keeping it all as one.
errors.New(fmt.Sprintf("This proprietary error happened! Stack trace: %s", message));
If you did that you wouldn't implement func (h *HttpError) Error() since you'd be relying on the embedded error for this.
I created following file structure in $GOPATH/src
bitbucket.org/MyName/ProjectName
I have follwoing files here
ProjectName
- controllers/
- meController.go
- app.go
In app.go I'm importing my controller like that:
import "bitbucket.org/MyName/ProjectName/controllers"
And in main func I'm trying to use it's method.
meController = new(controllers.meController)
m.Get("/", meController.Index)
My meController.go looks like this
package controllers
type meController struct {
}
func (controller *meController) Index () string {
return "Hello World"
}
But I'm getting this error:
./app.go:5: imported and not used: "bitbucket.org/MyName/ProjectName/controllers"
./app.go:12: undefined: meController
I don't have any idea how to get this to work.
Any ideas?
Thanks!
In Go, every symbol that starts with lowercase is not exported by the package. call your struct MeController and you'll be fine.