I am trying to use Go 1.18 go test -fuzz command to fuzz nil values so that I can ensure I didn't forget safety checks before attempting to dereference a pointer to a string.
Here is my attempt:
// main.go
package main
import (
"fmt"
)
func HandleString(s *string) {
// most common programmer error is dereferencing nil pointers without safety checks
fmt.Println(*s)
}
func main() {
s := "Hello, world"
HandleString(&s)
}
// main_test.go
package main
import "testing"
func FuzzHandleString(f *testing.F) {
h := "hello world"
for _, seed := range []*string{nil, new(string), &h} {
f.Add(seed)
}
f.Fuzz(func(t *testing.T, in *string) {
HandleString(in)
})
}
Unfortunately i get an error saying go fuzz doesn't support pointers and only supports the string datatype.
I found a workaround by writing my test like this:
package main
import "testing"
func FuzzHandleString(f *testing.F) {
h := "hello world"
for _, seed := range []string{"-1", "", h} {
f.Add(seed)
}
f.Fuzz(func(t *testing.T, in string) {
if in == "-1" {
HandleString(nil)
} else {
HandleString(&in)
}
})
}
This is a horrible design, and makes the seed data array not easily reusable , and requires logic in every fuzz function to trick my method into taking a nil value.
Surely there has to be a better way I didn't think of?
Thanks
Your code is awkward because this is not what fuzzing is for. Fuzzing is to throw random values at your functions to test edge cases you may not have thought about.
What you're doing is more like bounds testing. You have a known tricky inputs like nil, or empty string, or an empty array. Test them in their own unit tests.
Finally, I'd question why nil is a valid input to handleString. nil is not a string. It should be an error, unless there's a good reason otherwise, and you should be testing for that error.
Related
I am a beginner in Golang.
I have a problem with variable type assigning from user input.
When the user enters data like "2012BV352" I need to be able to ignore the BV and pass 2012352 to my next function.
There has a package name gopkg.in/validator.v2 in doc
But what it returns is whether or not the variable is safe or not.
I need to cut off the unusual things.
Any idea on how to achieve this?
You could write your own sanitizing methods and if it becomes something you'll be using more often, I'd package it out and add other methods to cover more use cases.
I provide two different ways to achieve the same result. One is commented out.
I haven't run any benchmarks so i couldn't tell you for certain which is more performant, but you could write your own tests if you wanted to figure it out. It would also expose another important aspect of Go and in my opinion one of it's more powerful tools... testing.
package main
import (
"fmt"
"log"
"regexp"
"strconv"
"strings"
)
// using a regex here which simply targets all digits and ignores everything else. I make it a global var and use MustCompile because the
// regex doesn't need to be created every time.
var extractInts = regexp.MustCompile(`\d+`)
func SanitizeStringToInt(input string) (int, error) {
m := extractInts.FindAllString(input, -1)
s := strings.Join(m, "")
return strconv.Atoi(s)
}
/*
// if you didn't want to use regex you could use a for loop
func SanitizeStringToInt(input string) (int, error) {
var s string
for _, r := range input {
if !unicode.IsLetter(r) {
s += string(r)
}
}
return strconv.Atoi(s)
}
*/
func main() {
a := "2012BV352"
n, err := SanitizeStringToInt(a)
if err != nil {
log.Fatal(err)
}
fmt.Println(n)
}
I'm new to golang; however based on my current knowledge I understand that a value-type and a reference-type can both fulfill an interface. But it seems in regards to type assertion, how you return a struct does matter. See the following:
package main
import (
"fmt"
)
type SomeError interface {
Error() string
}
type ConcreteError struct{}
func (ConcreteError) Error() string {
return "?"
}
func returnPointer() SomeError {
return &ConcreteError{}
}
func returnVal() SomeError {
return ConcreteError{}
}
func main() {
pointer := returnPointer()
value := returnVal()
_, pointerWithPointer := pointer.(*ConcreteError);
_, pointerWithValue := pointer.(ConcreteError);
_, valueWithValue := value.(ConcreteError);
_, valueWithPointer := value.(*ConcreteError)
fmt.Printf("Returning a pointer, assert using (*ConcreteError): %v\n", pointerWithPointer); // true
fmt.Printf("Returning a pointer, assert using (ConcreteError): %v\n", pointerWithValue); // false
fmt.Printf("Returning a value, assert using (ConcreteError): %v\n", valueWithValue); // true
fmt.Printf("Returning a value, assert using (*ConcreteError): %v\n", valueWithPointer); // false
}
So if my understanding is correct, the user needs to know how the struct is returned to correctly assert its type?
I'm going to guess and assume the standard practice in golang is to always return a pointer to a struct(i.e like *PathError)?
link to play: here
So if my understanding is correct, the user needs to know how the struct is returned to correctly assert its type?
It depends. If you need the type assertion to pass - you surely need to know the exact type of the value. a and *a are different types.
I'm going to guess and assume the standard practice in golang is to always return a pointer to a struct(i.e like *PathError)?
No.
I read about the interfaces a lot and I think I understand how it works. I read about the interface{} type and use it to take an argument of function. It is clear. My question (and what I don't understand) is what is my benefit if I am using it. It is possible I didn't get it entirely but for example I have this:
package main
import (
"fmt"
)
func PrintAll(vals []interface{}) {
for _, val := range vals {
fmt.Println(val)
}
}
func main() {
names := []string{"stanley", "david", "oscar"}
vals := make([]interface{}, len(names))
for i, v := range names {
vals[i] = v
}
PrintAll(vals)
}
Why is it better than this:
package main
import (
"fmt"
)
func PrintAll(vals []string) {
for _, val := range vals {
fmt.Println(val)
}
}
func main() {
names := []string{"stanley", "david", "oscar"}
PrintAll(names)
}
If you're always want to print string values, then the first using []interface{} is not better at all, it's worse as you lose some compile-time checking: it won't warn you if you pass a slice which contains values other than strings.
If you want to print values other than strings, then the second with []string wouldn't even compile.
For example the first also handles this:
PrintAll([]interface{}{"one", 2, 3.3})
While the 2nd would give you a compile-time error:
cannot use []interface {} literal (type []interface {}) as type []string in argument to PrintAll
The 2nd gives you compile-time guarantee that only a slice of type []string is passed; should you attempt to pass anything other will result in compile-time error.
Also see related question: Why are interfaces needed in Golang?
I have an error value which when printed on console gives me Token is expired
How can I compare it with a specific error value? I tried this but it did not work:
if err == errors.New("Token is expired") {
log.Printf("Unauthorised: %s\n", err)
}
Declaring an error, and comparing it with '==' (as in err == myPkg.ErrTokenExpired) is no longer the best practice with Go 1.13 (Q3 2019)
The release notes mentions:
Go 1.13 contains support for error wrapping, as first proposed in the Error Values proposal and discussed on the associated issue.
An error e can wrap another error w by providing an Unwrap method that returns w.
Both e and w are available to programs, allowing e to provide additional context to w or to reinterpret it while still allowing programs to make decisions based on w.
To support wrapping, fmt.Errorf now has a %w verb for creating wrapped errors, and three new functions in the errors package ( errors.Unwrap, errors.Is and errors.As) simplify unwrapping and inspecting wrapped errors.
So the Error Value FAQ explains:
You need to be prepared that errors you get may be wrapped.
If you currently compare errors using ==, use errors.Is instead.
Example:
if err == io.ErrUnexpectedEOF
becomes
if errors.Is(err, io.ErrUnexpectedEOF)
Checks of the form if err != nil need not be changed.
Comparisons to io.EOF need not be changed, because io.EOF should never be wrapped.
If you check for an error type using a type assertion or type switch, use errors.As instead. Example:
if e, ok := err.(*os.PathError); ok
becomes
var e *os.PathError
if errors.As(err, &e)
Also use this pattern to check whether an error implements an interface. (This is one of those rare cases when a pointer to an interface is appropriate.)
Rewrite a type switch as a sequence of if-elses.
This answer is for Go 1.12 and earlier releases.
Define an error value in a library
package fruits
var NoMorePumpkins = errors.New("No more pumpkins")
Do not create errors with errors.New anywhere in the code but return the predefined value whenever error occurs and then you can do the following:
package shop
if err == fruits.NoMorePumpkins {
...
}
See io package errors for reference.
This can be improved by adding methods to hide the check implementation and make the client code more immune to changes in fruits package.
package fruits
func IsNoMorePumpkins(err error) bool {
return err == NoMorePumpkins
}
See os package errors for reference.
Try
err.Error() == "Token is expired"
Or create your own error by implementing the error interface.
It's idiomatic for packages to export error variables that they use so others can compare against them.
E.g. If an error would came from a package named myPkg and was defined as:
var ErrTokenExpired error = errors.New("Token is expired")
You could compare the errors directly as:
if err == myPkg.ErrTokenExpired {
log.Printf("Unauthorised: %s\n", err)
}
If the errors come from a third party package and that doesn't use exported error variables then what you can do is simply to compare against the string you get from err.Error() but be careful with this approach as changing an Error string might not be released in a major version and would break your business logic.
The error type is an interface type. An error variable represents any value that can describe itself as a string. Here is the interface's declaration:
type error interface {
Error() string
}
The most commonly-used error implementation is the errors package's unexported errorString type:
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}
See this working code output (The Go Playground):
package main
import (
"errors"
"fmt"
"io"
)
func main() {
err1 := fmt.Errorf("Error")
err2 := errors.New("Error")
err3 := io.EOF
fmt.Println(err1) //Error
fmt.Printf("%#v\n", err1) // &errors.errorString{s:"Error"}
fmt.Printf("%#v\n", err2) // &errors.errorString{s:"Error"}
fmt.Printf("%#v\n", err3) // &errors.errorString{s:"EOF"}
}
output:
Error
&errors.errorString{s:"Error"}
&errors.errorString{s:"Error"}
&errors.errorString{s:"EOF"}
Also see: Comparison operators
Comparison operators compare two operands and yield an untyped boolean
value. In any comparison, the first operand must be assignable to the
type of the second operand, or vice versa.
The equality operators == and != apply to operands that are
comparable.
Pointer values are comparable. Two pointer values are equal if they
point to the same variable or if both have value nil. Pointers to
distinct zero-size variables may or may not be equal.
Interface values are comparable. Two interface values are equal if
they have identical dynamic types and equal dynamic values or if both
have value nil.
A value x of non-interface type X and a value t of interface type T
are comparable when values of type X are comparable and X implements
T. They are equal if t's dynamic type is identical to X and t's
dynamic value is equal to x.
Struct values are comparable if all their fields are comparable. Two
struct values are equal if their corresponding non-blank fields are
equal.
So:
1- You may use Error(), like this working code (The Go Playground):
package main
import (
"errors"
"fmt"
)
func main() {
err1 := errors.New("Token is expired")
err2 := errors.New("Token is expired")
if err1.Error() == err2.Error() {
fmt.Println(err1.Error() == err2.Error()) // true
}
}
output:
true
2- Also you may compare it with nil, like this working code (The Go Playground):
package main
import (
"errors"
"fmt"
)
func main() {
err1 := errors.New("Token is expired")
err2 := errors.New("Token is expired")
if err1 != nil {
fmt.Println(err1 == err2) // false
}
}
output:
false
3- Also you may compare it with exact same error, like this working code
(The Go Playground):
package main
import (
"fmt"
"io"
)
func main() {
err1 := io.EOF
if err1 == io.EOF {
fmt.Println("err1 is : ", err1)
}
}
output:
err1 is : EOF
ref: https://blog.golang.org/error-handling-and-go
It's being discouraged to compare errors by strings. Instead you should compare errors by value.
package main
import "errors"
var NotFound = errors.New("not found")
func main() {
if err := doSomething(); errors.Is(err, NotFound) {
println(err)
}
}
func doSomething() error {
return NotFound
}
It is especially useful if you are library author and would like to export errors so users can act differently on different type of errors. Standard library does it as well.
Problem with this approach is that exported values can be changed by anyone as Go doesn't support immutable values. Nothing prevents you, though, to use string as an error and make it const.
package main
type CustomError string
func (ce CustomError) Error() string {
return string(ce)
}
const NotFound CustomError = "not found"
func main() {
if err := doSomething(); errors.Is(err, NotFound) {
println(err)
}
}
func doSomething() error {
return NotFound
}
It is more verbose but safer approach.
You should first consider comparing errors by value, as described in other solutions with:
if errors.Is(err1, err2) {
// do sth
}
However in some cases the error returned from a function is a bit complex, e.g. an error is being wrapped multiple times, with a context being added to it in each function call like fmt.Errorf("some context: %w", err), and you may simply just want to compare the error message of two errors. In such cases you can do this:
// SameErrorMessage checks whether two errors have the same messages.
func SameErrorMessage(err, target error) bool {
if target == nil || err == nil {
return err == target
}
return err.Error() == target.Error()
}
func main() {
...
if SameErrorMessage(err1, err2) {
// do sth
}
}
Note that if you simply use
if err1.Error() == err2.Error() {
// do sth
}
You might face nil pointer dereference runtime error if either of err1 or err2 be nil.
To add to #wst 's answer, in some cases, the errors.Is(err, NotFound) approach may not work for reasons I am trying to figure out too. If someone knows, please let me know in the comments.
But I found a better approach to use it in the following way which was working for me:
if NotFound.Is(err) {
// do something
}
Where var NotFound = errors.New("not found") is an exported common error declared.
In my case, the solution was
if models.GetUnAuthenticatedError().Is(err) {
// Do something
}
I want to post one case where errors.Is could work well for custom errors with non-comparable values.
type CustomError struct {
Meta map[string]interface{}
Message string
}
func (c CustomError) Error() string {
return c.Message
}
var (
ErrorA = CustomError{Message: "msg", Meta: map[string]interface{}{"key": "value"}}
)
func DoSomething() error {
return ErrorA
}
func main() {
err := DoSomething()
if errors.Is(err, ErrorA) {
fmt.Println("error is errorA")
} else {
fmt.Println("error is NOT errorA")
}
}
Output
error is NOT errorA
Playground
The reason is errors.Is checks whether the target is comparable or not
func Is(err, target error) bool {
if target == nil {
return err == target
}
isComparable := reflectlite.TypeOf(target).Comparable()
The comparable type in Go are
booleans, numbers, strings, pointers, channels, arrays of comparable types, structs whose fields are all comparable types
Since the Meta map[string]interface{} of CustomError is NOT comparable, so errors.Is checks failed.
One workaround is declare the ErrorA = &CustomError{Message: "msg", Meta: map[string]interface{}{"key": "value"}} as pointer.
Can Go have optional parameters? Or can I just define two different functions with the same name and a different number of arguments?
Go does not have optional parameters nor does it support method overloading:
Method dispatch is simplified if it
doesn't need to do type matching as
well. Experience with other languages
told us that having a variety of
methods with the same name but
different signatures was occasionally
useful but that it could also be
confusing and fragile in practice.
Matching only by name and requiring
consistency in the types was a major
simplifying decision in Go's type
system.
A nice way to achieve something like optional parameters is to use variadic args. The function actually receives a slice of whatever type you specify.
func foo(params ...int) {
fmt.Println(len(params))
}
func main() {
foo()
foo(1)
foo(1,2,3)
}
You can use a struct which includes the parameters:
type Params struct {
a, b, c int
}
func doIt(p Params) int {
return p.a + p.b + p.c
}
// you can call it without specifying all parameters
doIt(Params{a: 1, c: 9})
The main advantage over an ellipsis (params ...SomeType) is that you can use the param struct with different parameter types.
For arbitrary, potentially large number of optional parameters, a nice idiom is to use Functional options.
For your type Foobar, first write only one constructor:
func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){
fb := &Foobar{}
// ... (write initializations with default values)...
for _, op := range options{
err := op(fb)
if err != nil {
return nil, err
}
}
return fb, nil
}
where each option is a function which mutates the Foobar. Then provide convenient ways for your user to use or create standard options, for example :
func OptionReadonlyFlag(fb *Foobar) error {
fb.mutable = false
return nil
}
func OptionTemperature(t Celsius) func(*Foobar) error {
return func(fb *Foobar) error {
fb.temperature = t
return nil
}
}
Playground
For conciseness, you may give a name to the type of the options (Playground) :
type OptionFoobar func(*Foobar) error
If you need mandatory parameters, add them as first arguments of the constructor before the variadic options.
The main benefits of the Functional options idiom are :
your API can grow over time without breaking existing code, because the constuctor signature stays the same when new options are needed.
it enables the default use case to be its simplest: no arguments at all!
it provides fine control over the initialization of complex values.
This technique was coined by Rob Pike and also demonstrated by Dave Cheney.
Neither optional parameters nor function overloading are supported in Go. Go does support a variable number of parameters: Passing arguments to ... parameters
No -- neither. Per the Go for C++ programmers docs,
Go does not support function
overloading and does not support user
defined operators.
I can't find an equally clear statement that optional parameters are unsupported, but they are not supported either.
You can pass arbitrary named parameters with a map. You will have to assert types with "aType = map[key].(*foo.type)" if the parameters have non-uniform types.
type varArgs map[string]interface{}
func myFunc(args varArgs) {
arg1 := "default"
if val, ok := args["arg1"]; ok {
arg1 = val.(string)
}
arg2 := 123
if val, ok := args["arg2"]; ok {
arg2 = val.(int)
}
fmt.Println(arg1, arg2)
}
func Test_test() {
myFunc(varArgs{"arg1": "value", "arg2": 1234})
}
Go doesn’t support optional parameters , default values and function overloading but you can use some tricks to implement the same.
Sharing one example where you can have different number and type of arguments in one function. It’s a plain code for easy understanding you need to add error handling and some logic.
func student(StudentDetails ...interface{}) (name string, age int, area string) {
age = 10 //Here Age and area are optional params set to default values
area = "HillView Singapore"
for index, val := range StudentDetails {
switch index {
case 0: //the first mandatory param
name, _ = val.(string)
case 1: // age is optional param
age, _ = val.(int)
case 2: //area is optional param
area, _ = val.(string)
}
}
return
}
func main() {
fmt.Println(student("Aayansh"))
fmt.Println(student("Aayansh", 11))
fmt.Println(student("Aayansh", 15, "Bukit Gombak, Singapore"))
}
So I feel like I'm way late to this party but I was searching to see if there was a better way to do this than what I already do. This kinda solves what you were trying to do while also giving the concept of an optional argument.
package main
import "fmt"
type FooOpts struct {
// optional arguments
Value string
}
func NewFoo(mandatory string) {
NewFooWithOpts(mandatory, &FooOpts{})
}
func NewFooWithOpts(mandatory string, opts *FooOpts) {
if (&opts) != nil {
fmt.Println("Hello " + opts.Value)
} else {
fmt.Println("Hello")
}
}
func main() {
NewFoo("make it work please")
NewFooWithOpts("Make it work please", &FooOpts{Value: " World"})
}
Update 1:
Added a functional example to show functionality versus the sample
You can encapsulate this quite nicely in a func similar to what is below.
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
fmt.Println(prompt())
}
func prompt(params ...string) string {
prompt := ": "
if len(params) > 0 {
prompt = params[0]
}
reader := bufio.NewReader(os.Stdin)
fmt.Print(prompt)
text, _ := reader.ReadString('\n')
return text
}
In this example, the prompt by default has a colon and a space in front of it . . .
:
. . . however you can override that by supplying a parameter to the prompt function.
prompt("Input here -> ")
This will result in a prompt like below.
Input here ->
You could use pointers and leave them nil if you don't want to use them:
func getPosts(limit *int) {
if optParam != nil {
// fetch posts with limit
} else {
// fetch all posts
}
}
func main() {
// get Posts, limit by 2
limit := 2
getPosts(&limit)
// get all posts
getPosts(nil)
}
Go language does not support method overloading, but you can use variadic args just like optional parameters, also you can use interface{} as parameter but it is not a good choice.
I ended up using a combination of a structure of params and variadic args. This way, I didn't have to change the existing interface which was consumed by several services and my service was able to pass additional params as needed. Sample code in golang playground: https://play.golang.org/p/G668FA97Nu
I am a little late, but if you like fluent interface you might design your setters for chained calls like this:
type myType struct {
s string
a, b int
}
func New(s string, err *error) *myType {
if s == "" {
*err = errors.New(
"Mandatory argument `s` must not be empty!")
}
return &myType{s: s}
}
func (this *myType) setA (a int, err *error) *myType {
if *err == nil {
if a == 42 {
*err = errors.New("42 is not the answer!")
} else {
this.a = a
}
}
return this
}
func (this *myType) setB (b int, _ *error) *myType {
this.b = b
return this
}
And then call it like this:
func main() {
var err error = nil
instance :=
New("hello", &err).
setA(1, &err).
setB(2, &err)
if err != nil {
fmt.Println("Failed: ", err)
} else {
fmt.Println(instance)
}
}
This is similar to the Functional options idiom presented on #Ripounet answer and enjoys the same benefits but has some drawbacks:
If an error occurs it will not abort immediately, thus, it would be slightly less efficient if you expect your constructor to report errors often.
You'll have to spend a line declaring an err variable and zeroing it.
There is, however, a possible small advantage, this type of function calls should be easier for the compiler to inline but I am really not a specialist.
Another possibility would be to use a struct which with a field to indicate whether its valid. The null types from sql such as NullString are convenient. Its nice to not have to define your own type, but in case you need a custom data type you can always follow the same pattern. I think the optional-ness is clear from the function definition and there is minimal extra code or effort.
As an example:
func Foo(bar string, baz sql.NullString){
if !baz.Valid {
baz.String = "defaultValue"
}
// the rest of the implementation
}