This question already has answers here:
How to compare Go errors
(9 answers)
Closed 7 months ago.
I create a err in my package and compare it with io.EOF, but the == operand is false. But their type and value are same? Why == operand return false?
func TestErr(t *testing.T) {
err := errors.New("EOF")
t.Log(err == io.EOF)
t.Logf("io err:%T,%v,%p", io.EOF, io.EOF, io.EOF)
t.Logf("my err:%T,%v,%p", err, err, err)
}
These two error are not equal because their pointers are not equal
error is an interface. It contains a pointer to the underlying value. The io.EOF is created by:
var EOF = errors.New("EOF")
If you look at errors.New:
func New(text string) error {
return &errorString{text}
}
type errorString struct {
s string
}
So, the io.EOF points to an instance of errorString struct, and the error you created also points to an instance of errorString struct with the same string value, but the two pointers are not the same.
If you really want to do this, you can unwrap the errors:
package main
import (
"errors"
"io"
)
func main() {
err := errors.New("EOF")
println(err.Error() == io.EOF.Error())
}
https://golang.org/pkg/builtin#error
Related
This question already has answers here:
Why these two errors are not equal [duplicate]
(2 answers)
Closed 2 years ago.
Can anyone please help me understand why "if err == errEOF" is not evaluating to TRUE and its only works with io.EOF. I know the Strings.Read function is returning io.EOF, but why can't we use the same type and value to evaluate the err?
https://play.golang.org/p/bCp4bZjKW-K
package main
import (
"errors"
"fmt"
"strings"
"io"
)
var errEOF = errors.New("EOF")
func main() {
r := strings.NewReader("ABCDEFGH")
buf := make([]byte, 4)
for {
n, err := r.Read(buf)
fmt.Println(n, err, buf[:n])
//if err == io.EOF { //Loop is breaking only when i use io.EOF
if err == errEOF { // If i use my own ErrEOF value, It is Not Breaking, Going forever
break
}
}
}
// Package errors implements functions to manipulate errors.
package errors
// New returns an error that formats as the given text.
func New(text string) error {
return &errorString{text}
}
If you look at the implementation of New in errors package, it just returns a new instance of errorString. So the var EOF = errors.New("EOF") from package io and your definition are two different errors altogether.
You should not be doing this, but the only way your errEOF will work is if you compare err.String() to errEOF.String(). But you should not be doing this anyways.
This question already has answers here:
Hiding nil values, understanding why Go fails here
(3 answers)
Closed 5 years ago.
Can someone provide some explanation about this code behaviour:
https://play.golang.org/p/_TjQhthHl3
package main
import (
"fmt"
)
type MyError struct{}
func (e *MyError) Error() string {
return "some error"
}
func main() {
var err error
if err == nil {
fmt.Println("[OK] err is nil ...")
}else{
fmt.Println("[KO] err is NOT nil...")
}
isNil(err)
var err2 *MyError
if err2 == nil {
fmt.Println("[OK] err2 is nil ...")
}else{
fmt.Println("[KO] err2 is NOT nil...")
}
isNil(err2)
}
func isNil(err error){
if err == nil {
fmt.Println("[OK] ... still nil")
}else{
fmt.Println("[KO] .. why not nil?")
}
}
Output is:
[OK] err is nil ...
[OK] ... still nil
[OK] err2 is nil ...
[KO] .. why err2 not nil?
I found this post Check for nil and nil interface in Go but I still don't get it...
error is a built-in interface, and *MyError implements that interface. Even though the value of err2 is nil, when you pass it to isNil, the function gets a non-nil interface value. That value contains information about the type (*MyError) and the value itself, which is a nil pointer.
If you try printing err in isNil, you'll see that in the second case, you get "some error" even though err2 is nil. This demonstrates why err is not nil in that case (it has to contain the type information).
From my understanding your var err2 *MyError definition is generating a pointer to the struct definition and NOT an actual instantiated object.
In Go interface types are represented by a structure with 2 fields: one denotes its actual type and the other is a pointer to the value.
It means that an interface value is never equal to nil unless the value you passed is actually a nil value.
Relevant and good talk: GopherCon 2016: Francesc Campoy - Understanding nil
I am probably missing something really simple here:
package main
import (
"fmt"
"strconv"
"reflect"
)
func main() {
s := "abd"
fmt.Println(s)
_, err := strconv.Atoi(s)
if err != nil {
fmt.Println(err)
}
fmt.Println(reflect.TypeOf(err))
fmt.Println(err.Err)
}
I am trying to extract the error itself e.g. ErrSyntax or ErrRange, but I am not able to do so.
After looking at:
https://golang.org/src/strconv/atoi.go?s=3604:3671#L16
I see that err is a pointer to strconv.NumError
15 // A NumError records a failed conversion.
16 type NumError struct {
17 Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
18 Num string // the input
19 Err error // the reason the conversion failed (ErrRange, ErrSyntax)
20 }
And Err is the field that holds either ErrRange of ErrSyntax. Therefore, I thought that err.Err would work, but I get:
err.Err undefined (type error has no field or method Err
Err is public, am I missing something with visibility rules?
What am I missing?
Use a type assertion to get the *strconv.NumError value:
if e, ok := err.(*strconv.NumError); ok {
fmt.Println("e.Err", e.Err)
}
playground example
This question already has answers here:
Hiding nil values, understanding why Go fails here
(3 answers)
Closed 7 years ago.
I have a situation where the value of a variable "err error" value can only be "nil" but asserts "( err == nil ) == false" once it has been reassigned.
Example code below:
package main
import (
"fmt"
"log"
)
type TestError struct {
Message string
}
func (e *TestError) Error() string {
return e.Message
}
func NewTestError(err error) *TestError {
if err == nil {
return nil
}
log.Printf("NewTestError( ... ): creating new NewTestError err = %s", err)
return &TestError{Message: err.Error()}
}
func main() {
var err error
_, err = fmt.Printf("excuse.\n")
err = NewTestError(err)
log.Printf("main( ... ): err == nil. %v", (err == nil))
log.Printf("main( ... ): err = %#v", err)
}
I get the following output from the above code:
excuse.
2015/07/30 08:28:28 main( ... ): err == nil. false
2015/07/30 08:28:28 main( ... ): err = (*main.TestError)(nil)
How can those last two lines be output?
For an interface value (like an error value) to compare equal to nil, both the actual contained value and the actual contained type have to be nil. In your case you have an interface value, which holds a nil pointer, but a *TestError (i.e. non-nil) type.
PS. Just in case it's not clear what are these "interface values", you can check this http://research.swtch.com/interfaces
In the second case you're printing the interface instances information which is the type and the value, type being (*main.TestError) value being (nil). In the first case what you're actually comparing isn't nil because it's also the interface.
One of the functions I am running: image.Decode()
The image.Decode function takes in an io.Reader && and the io.Reader function takes in a []byte.
When I pass in a []uint8, if gives me this error:
panic: image: unknown format
How do I convert the []uint8 to []byte?
UPDATE
The error is happening at the starred area because image.Decode can't read the variable xxx.
package main
import (
"github.com/nfnt/resize"
"image"
"image/jpeg"
"fmt"
"launchpad.net/goamz/aws"
"launchpad.net/goamz/s3"
"bytes"
"encoding/json"
"io/ioutil"
"os"
"reflect"
)
type Data struct {
Key string
}
func main() {
useast := aws.USEast
connection := s3.New(auth, useast)
mybucket := connection.Bucket("bucketName")
image_data, err := mybucket.Get("1637563605030")
if err != nil {
panic(err.Error())
} else {
fmt.Println("success")
}
xxx := []byte(image_data)
******* THIS IS WHERE THE ERROR OCCURS **************
original_image, _, err := image.Decode(bytes.NewReader(xxx))
******* THIS IS WHERE THE ERROR OCCURS END **************
if err != nil {
fmt.Println("Shit")
panic(err.Error())
} else {
fmt.Println("Another success")
}
new_image := resize.Resize(160, 0, original_image, resize.Lanczos3)
if new_image != nil {
fmt.Println("YAY")
}
}
The Go Programming Language Specification
Numeric types
uint8 the set of all unsigned 8-bit integers (0 to 255)
byte alias for uint8
package main
import "fmt"
func ByteSlice(b []byte) []byte { return b }
func main() {
b := []byte{0, 1}
u8 := []uint8{2, 3}
fmt.Printf("%T %T\n", b, u8)
fmt.Println(ByteSlice(b))
fmt.Println(ByteSlice(u8))
}
Output:
[]uint8 []uint8
[0 1]
[2 3]
You have misdiagnosed your problem.
As the other answers have explained, there's no problem passing a []uint8 where a []byte is required. If this was your problem, you'd be getting a compile time error. You aren't. A panic is a runtime error, and it's being thrown by the image library when it reads the data in the slice.
In fact, the image library is only partially your problem. See http://golang.org/src/pkg/image/format.go. It's returning an error message because it doesn't recognize the image format of the data in the slice. Your code, which calls image.Decode() is calling panic when image.Decode() returns the error message.
If you have a variable imageData that is []uint8 you may pass []byte(imageData)
See http://golang.org/ref/spec#Conversions