#why the reference is required here ?

115 messages · Page 1 of 1 (latest)

steady talon
#

that's not the only thing it does

vernal foxBOT
#

    func As(err error, target any) bool

As finds the first error in err's tree that matches target, and if one is found, sets target to that error value and returns true. Otherwise, it returns false....

More documentation omitted

steady talon
#

the "and if one is found, sets target to that error value" is why a pointer is required

molten berry
#

!go

package main 

import ("fmt";"errors";"os")


func main() {
    var a error = errors.New("error a")
    var b *os.PathError

    tst := errors.As(a, &b)

    if tst == true {
        fmt.Println(a)
        fmt.Println(b)
    }else {
        fmt.Println(tst)
    }

}
steady talon
#

i've seen you discussing this recently, so tl;dr:

errors.Is checks if any error in the wrapped error is equal to a certain error value
errors.As checks if any error in the wrapped error has a certain type (and gives you the value of that type if so)

#

value vs type

molten berry
#

and finally i did

molten berry
#
package main 

import ("fmt";"errors")


func main() {
    var one error = errors.New("error one")
    var two *error = &one

    fmt.Println(errors.Is(one, *two))

}
steady talon
#

it's not quite "referencing"

#

from the docs:

An error is considered to match a target if it is equal to that target or if it implements a method Is(error) bool such that Is(target) returns true.

#

so either equal as determined by == or by an Is method on the error type

molten berry
#

how equal ?

#

var one error = error
var two error = error

it is false

#

but if

var one error = error
var two error = one

#

it is true

steady talon
#

from the spec:

Interface types that are not type parameters are comparable. Two interface values are equal if they have identical dynamic types and equal dynamic values or if both have value nil.

#

remember that errors.New is not the only way to make an error

#

anything that implements Error() string is an error

#

you could have an integer type be an error, then having two completely unrelated assignments of that be equal

molten berry
#

i see

molten berry
steady talon
#

if either == or Is is true

#

i'm not sure how else to explain that

#

it checks both

molten berry
#

i really didn't understand what u said

steady talon
#

it checks if the two errors are equal by ==

#

if so, it returns true

#

if not, it checks for an Is method and calls that

molten berry
#

so is uses == ?

steady talon
#

yes, that is what i said

molten berry
#

so basically it checks the memory address of both errors

steady talon
#

no

#

it uses ==

molten berry
#

yes

#

if two error types equal

#

means they have the same address

steady talon
#

no, it doesn't

molten berry
#
package main 

import ("fmt";"errors")


func main() {
    var one error = errors.New("error one")
    var two *error = &one

    fmt.Println(&one)
    fmt.Println(two)

}
#

0xc000022070
0xc000022070

steady talon
#

two equal errors having the same address does not mean that non-equal addresses cannot be equal

#

you proved one direction, not the other

molten berry
#

let me try again

#
package main 

import ("fmt";"errors";"os")


func main() {
    var one *os.LinkError
    var two *os.PathError

    fmt.Println(errors.Is(one, two))

}
#

panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x30 pc=0x4117e0]

#

see

steady talon
#

!go

package main

type CustomError int

func (CustomError) Error() string {
    return "CustomError"
}

func main() {
    one := CustomError(5)
    two := CustomError(5)
    fmt.Printf("%p\n", &one)
    fmt.Printf("%p\n", &two)
    fmt.Println(errors.Is(one, two))
}
molten berry
#

it compares the memory addresses

steady talon
#

idk if the bot sees thread messages

#

run that in the playground

molten berry
#

ok let me try

steady talon
#

it's incessant

#

try having an open mind

#

it's like you think you're in some sort of argument with everyone 😂 we're just trying to help

molten berry
#

0xc00000a0b8
0xc00000a0d0
true

but it doesn't prove anything both variables use the same type which the same address

steady talon
#

types don't have addresses

molten berry
#

i apologies for any inconviniece

steady talon
#

they're two variables with two different memory addresses, and somehow == is still true

#

it must mean they're not comparing memory addresses 🙂

molten berry
#

ok let me try harder brother

steady talon
#

if the dynamic type of an interface is a pointer, yes, you would be comparing memory addresses

#

but not all errrors have a dynamic type of a pointer

#

in particular, the return type of errors.New is a pointer under the hood, yes

#

but errors.New is not the only way to get an error value

molten berry
#
package main 

// is :
// as : 

import ("fmt";"errors")

func main() {
    var one error = errors.New("error happened")
    var address_one *error = &one

    var two error = errors.New("error happened")
    var address_two *error = &two


    fmt.Println(address_one)
    fmt.Println(address_two)

    fmt.Println(errors.Is(one, two))
}
0xc00008a030
0xc00008a050
false
steady talon
#

sure, but the fact that two errors with different addresses returns false here does not mean that all errors with different addresses return false

#

you've got your logic backwards here

molten berry
#

what i want to say is if an error uses the same error addresses of another error it is for sure true other than this it is false which means is compares the memory address of two error types and checks if they are sharing the same memory address

steady talon
#

i'm not so sure why you're so fixated on addresses

#

it's not inherent to comparing interfaces

#

== is simply applied on the dynamic value

#

could the dynamic value be a pointer? sure, but it could also be a string, integer, etc.

molten berry
#

it is all about compile time

#

not run-time

steady talon
#

no, it is all about runtime

#

that's what interfaces are

#

the dynamic, rather than static, type

molten berry
#

we both undestand how this works but we cannot agree

#

hhhhh

steady talon
#

i'm really not so sure you understand, given this conversation so far

molten berry
#

ok let's exclude the memory addresses

#

if two different variables have the same error type

#

should it be true or false ?

#

of course false

#

do u agree ?

steady talon
#

no, if they have the same type, then an equality check needs to happen

molten berry
#

what would the result of is be ?

steady talon
#

there's not enough information, an equality check needs to happen

#

you have two errors of the same type that are the same or different

molten berry
#
package main 

// is :
// as : 

import ("fmt";"errors")

func main() {
    var one error = errors.New("error happened")
    var two error = errors.New("error happened")

    fmt.Println(errors.Is(one, two))
    fmt.Println(one == two)
}```
#

false
false

steady talon
#

sure, but you can't unequivocally say false

#

== was applied to the error values

molten berry
#

that is wrong

#

u are showing me the memory addresses of two different variables not errors

steady talon
#

they are error variables

molten berry
#

do you know what memory address is ?

#

with all of my respect

steady talon
#

ok, how about ```go
package main

import (
"errors"
"fmt"
)

type CustomError int

func (CustomError) Error() string {
return "CustomError"
}

func main() {
var one error = CustomError(5)
var two error = CustomError(5)
fmt.Printf("%p\n", &one)
fmt.Printf("%p\n", &two)
fmt.Println(errors.Is(one, two))
}

#

spoiler alert: the answer is the same

#

you seem to be conflating the fact that dynamic values can themselves be pointers

#

but they need not be

steady talon
molten berry
molten berry
#

anyways