I am constantly thinking about the Go language and how things work. Lately I have been thinking how everything in Go is by value. We see this when we pass values to functions, when we iterate over slices and when we perform type assertions. In every case, copies of the values that are stored in these data structures are returned. When I first started learning Go this threw me off, but I have come to appreciate the reasonability this brings to our code.

I started to question what would happen if I made a copy of an interface value that was storing a value and not a pointer. Would each new interface value get their own copy or would they share the value? To get a definitive answer I wrote a small program to inspect the interface value.

https://play.golang.org/p/KXvtpd9_29

Listing 1

06 package main
07
08 import (
09     "fmt"
10     "unsafe"
11 )
12  
13 // notifier provides support for notifying events.
14 type notifier interface {
15     notify()
16 }
17  
18 // user represents a user in the system.
19 type user struct{
20     name string
21 }
22  
23 // notify implements the notifier interface.
24 func (u user) notify() {
25     fmt.Println("Alert", u.name)
26 }

In Listing 1 on line 14 we see the declaration of an interface type named notifier with a single method named notify. Then on line 19 we have the declaration of a concrete type named user with the implementation of the notifier interface on line 24. We now have an interface and a concrete type to work with.

Listing 2

28 // inspect allows us to look at the value stored
29 // inside the interface value.
30 func inspect(n *notifier, u *user) {
31     word := uintptr(unsafe.Pointer(n)) + uintptr(unsafe.Sizeof(&u))
32     value := (**user)(unsafe.Pointer(word))
33     fmt.Printf("Addr User: %p  Word Value: %p  Ptr Value: %v\n", u, *value, **value)
34 }

In Listing 2 we have the inspect function that starts on line 30. This function gives us a pointer to the second word of the interface value. With this pointer we can inspect the value of the second word of the interface and the user value that the second word points to. We need to review these values to really understand the mechanics of the interface.

Listing 3

36 func main() {
37
38     // Create a notifier interface and concrete type value.
39     var n1 notifier
40     u := user{"bill"}
41
42     // Store a copy of the user value inside the notifier
43     // interface value.
44     n1 = u
45
46     // We see the interface has its own copy.
47     // Addr User: 0x1040a120  Word Value: 0x10427f70  Ptr Value: {bill}
48     inspect(&n1, &u)
49
50     // Make a copy of the interface value.
51     n2 := n1
52 	
53     // We see the interface is sharing the same value stored in
54     // the n1 interface value.
55     // Addr User: 0x1040a120  Word Value: 0x10427f70  Ptr Value: {bill}
56     inspect(&n2, &u)
57
58     // Store a copy of the user address value inside the
59     // notifier interface value.
60     n1 = &u
61
62     // We see the interface is sharing the u variables value
63     // directly. There is no copy.
64     // Addr User: 0x1040a120  Word Value: 0x1040a120  Ptr Value: {bill}
65     inspect(&n1, &u)
66 }

Listing 3 shows the main function which starts on line 36. The very first thing we do on line 39 is declare a variable named n1 of interface type notifier set to its zero value. Then on line 40 we declare a variable named u of type user set with the string “bill”.

#go

Copying Interface Values In Go
1.30 GEEK