What golang compiler will do when fmt.Println() - go

I'm trying to understand how to check if two objects are the same when they implement the same interface.
Here is the example code:
package main
import (
"fmt"
)
type shout interface {
echo()
}
type a struct {}
func (*a) echo () {
fmt.Println("a")
}
type b struct {}
func (*b) echo () {
fmt.Println("b")
}
func compare(a, b shout) {
//fmt.Println(&a, &b)
if a == b {
fmt.Println("same")
} else {
fmt.Println("not same")
}
}
func main() {
a1 := &a{}
b1 := &b{}
a2 := &a{}
a1.echo()
b1.echo()
compare(a1, b1)
compare(a1, a2)
compare(a1, a1)
}
https://play.golang.org/p/qo9XnbthMw
The result is:
not same
not same
same
a1 and a2 are not the same
But if uncomment the line#22
fmt.Println(&a, &b)
The result is:
0x1040a120 0x1040a128
not same
0x1040a140 0x1040a148
same
0x1040a158 0x1040a160
same
Does anyone can figure out what happened here?
Does the Golang compiler optimize something?
Thanks

This appears to be a more complicated example of https://github.com/golang/go/issues/8938.
The relevant parts of the Go spec are https://golang.org/ref/spec#Comparison_operators
Pointers to distinct zero-size variables may or may not be equal.
and https://golang.org/ref/spec#Size_and_alignment_guarantees
Two distinct zero-size variables may have the same address in memory.
Based on the title of the issue linked above (cmd/compile: optimisations change the behaviour of *struct{}), the difference is due to compiler optimizations.

This is expected behavior. For background, == is an operator which compares the value of two objects. This is known as object equality. Comparing their pointer value, or their identity, is different. See the top answer on this similar post.
When you ask a1 == b1, you receive false because a1 is an instance of the a struct, whereas b1 is an instance of the b struct. Therefore, even though they implement the same interface, they are not == to each other. Consider your a struct and b struct where they had additional and different methods implemented in both (so a has an additional method foo() and b has an additional method bar()). Although a and b would implement the same interface, they would not be the same, nor would you expect or want them to be.
When you ask if a1 == a2, you receive true because a1 and a2 are just separate instances of the same struct. Referencing the post I linked above, a1 and a2 are equal, but do not share the same identity.
Finally, when you ask if a1 == a1, you are asking if the same instance of the same object is equal to itself, which of course is true. In this case, a1 shares both equality and identity with a1.

You should use reflect.DeepEqual to compare struct, slice and map.
package main
import (
"fmt"
)
type a struct{}
func main() {
a1 := &a{}
a2 := &a{}
fmt.Printf("%p\n", a1)
if a1 == a2 {
fmt.Println("same")
} else {
fmt.Println("not same")
}
}
The result is:
0x196a9c
not same
Using reflect.DeepEqual as below:
package main
import (
"fmt"
"reflect"
)
type a struct{}
func main() {
a1 := &a{}
a2 := &a{}
fmt.Printf("%p\n", a1)
if a1 == a2 {
fmt.Println("same")
} else {
fmt.Println("not same")
}
fmt.Println(reflect.DeepEqual(a1, a2))
}
The Result is:
0x196a9c
same
true
Just golang compiler optimization i guess.

Related

How to make a function with inferred nillable comparable generics?

Consider the following function:
func NilCompare[T comparable](a *T, b *T) bool {
if a == nil && b == nil {
// if both nil, we consider them equal
return true
}
if a == nil || b == nil {
// if either is nil, then they are clearly not equal
return false
}
return *a == *b
}
This function works. However, when I call it, I must supply the type, as Go cannot infer (cannot infer T) it, e.g. NilCompare[string](a, b), where a and b are *string.
If I modify T to be *comparable and a and b to be T, I get this error instead:
cannot use type comparable outside a type constraint: interface is (or embeds) comparable
I am using Go 1.19.2.
$ go version
go version go1.19.2 linux/amd64
Ironically, my IDE (GoLand 2022.2.3) believes that the above function should be inferrable.
Is there a way to make a function that take nillable comparable and make it inferrable? Or am I doing it correct, but I need to help the go function along?
Type inference just works, in this case. You simply can't infer T using literal nil, as NilCompare(nil, nil) because that doesn't really carry type information.
To test your function with nils do this:
package main
import "fmt"
func main() {
var a *string = nil
var b *string = nil
// a and b are explicitly typed
res := NilCompare(a, b) // T inferred
fmt.Println(res) // true
}
this also would work:
func main() {
// literal nil converted to *string
res := NilCompare((*string)(nil), (*string)(nil)) // T inferred
fmt.Println(res) // true
}

Confused by interface embeded in struct in golang

Like code here, when embedding an interface A into struct B, and then set A to aa which is an instance of AA. Both B and AA have element X, when call b.X I just got B.X. How can I get b.AA.X? I know this syntax is wired, but I just want to figure out how var b is stored in the memory, I tried some unsafe syntax, no way to get b.A.X.:
package main
import (
"fmt"
"unsafe"
)
type A interface {
Hello() string
}
type B struct {
A
X string
}
type AA struct {
num int
X string
}
func (aa AA) Hello() string {
return fmt.Sprintf("hello %d from %s", aa.num, aa.X)
}
func main() {
aa := AA{200, "golang"}
b := B{A: aa, X: "python"}
fmt.Println(b.X) // output: python
fmt.Printf("--->%d\n", ((*AA)(unsafe.Pointer(&b.A)).num)) // output: --->17667104
fmt.Printf("===>%+v\n", b.A) // output: ===>{num:200 X:golang}
}
Embedded fields are accessed by their type name, and fields of an interface are only accessible by asserting the underlying type, so b.A.(AA).X will get you field X of the underlying AA that's in b.A. But if you're needing to access fields, you probably shouldn't be embedding the interface type anyway, you should be embedding the concrete type.

Identity comparison in golang?

I've been trying to build a set of structs that have a base struct as their foundation and variants built on top of that. I've found, however, that there doesn't seem to be a way for the struct to identify itself when the common code is in the base struct. How should I be doing this?
package main
import (
"fmt"
)
type Base interface {
IsMe(other Base) bool
}
type Block struct {
}
func (b *Block) IsMe(other Base) bool {
return b == other
}
type Block2 struct {
Block
}
func main() {
b1 := &Block{}
b2 := &Block2{}
fmt.Printf("b1.IsMe(b1): %v\n", b1.IsMe(b1))
fmt.Printf("b1.IsMe(b2): %v\n", b1.IsMe(b2))
fmt.Printf("b2.IsMe(b1): %v\n", b2.IsMe(b1)) // Wrong result!
fmt.Printf("b2.IsMe(b2): %v\n", b2.IsMe(b2)) // Wrong result!
}
If you really want to do it the fake inheritance way then you can certainly do it the way you did it but it really only works with unsafe or reflect because the language is not designed for what you want to do.
Your problem starts with where x.IsMe comes from when using embedding. When you write
type Block struct {}
func (b *Block) IsMe(other Base) bool { return b == other }
type Block2 struct { Block }
the method IsMe is actually associated and bound to Block instead of Block2. So calling IsMe on an instance of Block2 is really only calling it on Block, in detail:
b2 := Block2{}
fmt.Println(b2.IsMe) // 0x21560
fmt.Println(b2.Block.IsMe) // 0x21560
Both methods have the same address. This shows that even though b2 has the method IsMe, that method is only propagated from Block to the outside of Block2 and not inherited. This in turn means that you are always running effectively this code:
b1 := Block{}
b2 := Block2{}
b2_embedded_block := b2.Block
b2_embedded_block.IsMe(b2)
b2_embedded_block.IsMe(b1)
// ...
which obviously cannot work since you are comparing two completely different instances.
What you really should do is to use some function outside of your embedding chain to decide equality. Example (On Play):
func IsEq(a,b Base) bool {
return a == b
}
This actually compares the right instances.
package main
import (
"fmt"
"reflect"
)
type Base interface {
IsMe(other Base) bool
}
type Block struct {
_ [1]byte // size of struct must be greater than zero
}
func (b *Block) IsMe(other Base) bool {
x := reflect.ValueOf(b)
y := reflect.ValueOf(other)
return x.Pointer() == y.Pointer()
}
type Block2 struct {
Block // "parent" needs to be first element
}
func main() {
b1 := &Block{}
b2 := &Block2{}
fmt.Printf("b1.IsMe(b1): %v\n", b1.IsMe(b1))
fmt.Printf("b1.IsMe(b2): %v\n", b1.IsMe(b2))
fmt.Printf("b2.IsMe(b1): %v\n", b2.IsMe(b1))
fmt.Printf("b2.IsMe(b2): %v\n", b2.IsMe(b2))
}
https://play.golang.org/p/Dx0Ze3euFY

What's the difference between these functions in golang?

I'm new to Go programming and wondering what's the difference (if any) there between
a.
func DoSomething(a *A) {
b = a
}
b.
func DoSomething(a A) {
b = &a
}
If you are actually asking what the difference of those b's are, one is a pointer to the object passed as an argument to DoSomething, and the other is a pointer to a copy of the object passed as an argument to DoSomething.
https://play.golang.org/p/ush0hDZsdE
type A struct {
f string
}
func DoSomethingPtr(a *A) {
b := a
b.f = "hi"
}
func DoSomething(a A) {
b := &a
b.f = "hey"
}
func main() {
x := A{"hello"}
DoSomething(x)
fmt.Println(x)
DoSomethingPtr(&x)
fmt.Println(x)
}
The variable b would be assigned a different value in each function. The values are different because one is passing a copied value and the other is passing a pointer to the original value in memory.
package main
import "fmt"
type A string
func DoSomethingPtr(a *A) {
fmt.Println(a)
}
func DoSomething(a A) {
fmt.Println(&a)
}
func main() {
x := A("hello")
DoSomething(x)
DoSomethingPtr(&x)
}
Here is the executable proof.
In general, these two functions will assign different values to b. The second one makes a copy of the argument, and so the a inside the function generally has a different memory address than whatever input is passed into the function. See this playground example
package main
type A struct{
x int
}
var b *A
func d(a *A) {
b = a
}
func e(a A) {
b = &a
}
func main() {
var a = A{3}
println(&a)
d(&a)
println(b)
e(a)
println(b)
}
Interestingly, if you make the type A an empty struct instead, and initialize var a = A{}, you actually see the same value for b in the println statements.
That's because for the empty-struct type, there can only really only ever be 1 value, and its immutable, so all instances of it share the same memory address?

Golang print "nil"

i am reading the golang tutorial: https://tour.golang.org/moretypes/10
And i am confused about how fmt.Println prints the nil value, hope you could help me out.
package main
import "fmt"
func main() {
var z []int
fmt.Println("z: ", z)
if z == nil {
fmt.Println("z is nil!")
}
fmt.Println("nil:", nil)
}
the result is:
z: []
z is nil!
nil: <nil>
Since z is a nil, why is z printed as [] but not <nil>?
thanks!
The fmt package uses reflection to determine what to print. Since the type of z is a slice, fmt uses the [] notation.
Since slices, channels, interfaces and pointers can all be nil, it helpful if fmt prints something different when it can. If you want more context, use the %v format: http://play.golang.org/p/I1SAVzlv9f
var a []int
var b chan int
var c *int
var e error
fmt.Printf("a:%#v\n", a)
fmt.Printf("b:%#v\n", b)
fmt.Printf("c:%#v\n", c)
fmt.Printf("e:%#v\n", e)
Prints:
a:[]int(nil)
b:(chan int)(nil)
c:(*int)(nil)
e:<nil>
The word nil means : not initialized.
In this case you are initializing the slide but no values have bean assigned yet.
Remember PICS (Pointers, Interfaces, CHANNELS , and SLIDES )are all already
initialized.

Resources