Skip to content

Commit

Permalink
feat(p/ufmt): add ufmt.Errorf (#1767)
Browse files Browse the repository at this point in the history
# Description

Added the `Errorf` function to `ufmt` based on `ufmt.Sprintf`. 

Previously, formatting errors involved a method like using
`errors.New(ufmt.Sprintf(XXX))`, but this approach is not only
cumbersome but also, as using `Errorf` is recommended in Go, I have
newly incorporated it.

## Usage

### Simple Error

This example demonstrates the process of using `Errorf` to format and
print error messages.

```go
package main

import (
	"gno.land/p/demo/ufmt"
)

func foo() error {
	return fmt.Errorf("an error occurred in simpleFunction")
}

func main() {
	if err := foo(); err != nil {
             println("Error:", err)
	}
}
```

### With Panic

Using panic is the recommended practice in [effective
gno](<https://docs.gno.land/concepts/effective-gno/#embrace-panic>), In
this example, format the error and then output the error message with
`panic`.

```go
package main

import (
	"gno.land/p/demo/ufmt"
)


func foo() {
	msg := ufmt.Errorf("error: %s", "something went wrong")
	panic(msg)
}
```

---------

Co-authored-by: Morgan <[email protected]>
  • Loading branch information
notJoon and thehowl authored Mar 13, 2024
1 parent 55db42e commit 3481a03
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 0 deletions.
32 changes: 32 additions & 0 deletions examples/gno.land/p/demo/ufmt/ufmt.gno
Original file line number Diff line number Diff line change
Expand Up @@ -96,3 +96,35 @@ func Sprintf(format string, args ...interface{}) string {
}
return buf
}

// errMsg implements the error interface.
type errMsg struct {
msg string
}

// Error defines the requirements of the error interface.
// It functions similarly to Go's errors.New()
func (e *errMsg) Error() string {
return e.msg
}

// Errorf is a function that mirrors the functionality of fmt.Errorf.
//
// It takes a format string and arguments to create a formatted string,
// then sets this string as the 'msg' field of an errMsg struct and returns a pointer to this struct.
//
// This function operates in a similar manner to Go's fmt.Errorf,
// providing a way to create formatted error messages.
//
// The currently formatted verbs are the following:
//
// %s: places a string value directly.
// If the value implements the interface interface{ String() string },
// the String() method is called to retrieve the value.
// %d: formats an integer value using package "strconv".
// Currently supports only uint, uint64, int, int64.
// %t: formats a boolean value to "true" or "false".
// %%: outputs a literal %. Does not consume an argument.
func Errorf(format string, args ...interface{}) error {
return &errMsg{Sprintf(format, args...)}
}
49 changes: 49 additions & 0 deletions examples/gno.land/p/demo/ufmt/ufmt_test.gno
Original file line number Diff line number Diff line change
Expand Up @@ -44,3 +44,52 @@ func TestSprintf(t *testing.T) {
})
}
}

func TestErrorf(t *testing.T) {
tests := []struct {
name string
format string
args []interface{}
expected string
}{
{
name: "simple string",
format: "error: %s",
args: []interface{}{"something went wrong"},
expected: "error: something went wrong",
},
{
name: "integer value",
format: "value: %d",
args: []interface{}{42},
expected: "value: 42",
},
{
name: "boolean value",
format: "success: %t",
args: []interface{}{true},
expected: "success: true",
},
{
name: "multiple values",
format: "error %d: %s (success=%t)",
args: []interface{}{123, "failure occurred", false},
expected: "error 123: failure occurred (success=false)",
},
{
name: "literal percent",
format: "literal %%",
args: []interface{}{},
expected: "literal %",
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := Errorf(tt.format, tt.args...)
if err.Error() != tt.expected {
t.Errorf("Errorf(%q, %v) = %q, expected %q", tt.format, tt.args, err.Error(), tt.expected)
}
})
}
}

0 comments on commit 3481a03

Please sign in to comment.