-
Notifications
You must be signed in to change notification settings - Fork 350
chapter2: How you can get duplicated go.itab interface definitions #7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
That makes perfect sense @siebenmann, thanks for the great explanation. I've added an exact reproduction of what you've described here. Layout: $ tree
.
├── A
│ └── lib.go
├── B
│ └── lib.go
├── C
│ └── lib.go
├── D
│ └── lib.go
└── main.go As you've described:
package A
type Calc struct{}
func (c *Calc) Add(a, b int32) int32 { return a + b }
package B
type Adder interface{ Add(a, b int32) int32 }
package C
import (
"github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/A"
"github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/B"
)
func Add(a, b int32) int32 {
var adder B.Adder = &A.Calc{}
return adder.Add(a, b)
}
package D
import (
"github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/A"
"github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/B"
)
func Add(a, b int32) int32 {
var adder B.Adder = &A.Calc{}
return adder.Add(a, b)
}
package main
import (
"fmt"
"github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/C"
"github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/D"
)
func main() {
fmt.Println(C.Add(10, 32))
fmt.Println(D.Add(10, 32))
} Looking at the output of $ go build -x
# ...
packagefile github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/C=$HOME/.cache/go-build/ff/ffc441d2cc7fd2bd9e12722f11fd3407dc4280577c0c74f8cb5241d72792d554-d
packagefile github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/D=$HOME/.cache/go-build/7c/7cc79061754b8fa877646bcbf5f10814217ac3dc48fc66c5964f08dd823695de-d
# ... We can see the linker importing the archives for both package Now if we look for $ go tool nm $HOME/.cache/go-build/ff/ffc441d2cc7fd2bd9e12722f11fd3407dc4280577c0c74f8cb5241d72792d554-d | grep 'itab\.'
af7 R go.itab.*github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/A.Calc,github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/B.Adder
$ go tool nm $HOME/.cache/go-build/7c/7cc79061754b8fa877646bcbf5f10814217ac3dc48fc66c5964f08dd823695de-d | grep 'itab\.'
af7 R go.itab.*github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/A.Calc,github.com/teh-cmc/go-internals/chapter2_interfaces/issue_7/B.Adder We see that the |
I've added a link to this discussion in the relevant part of chapter 2; and will be closing this now. Hopefully I'll take the time to update chapter 2 with all these learnings some day. |
You asked why go.itabs are dupok. I believe the fundamental reason is that Go can be statically creating iface structures outside of either the package that defines the type or the package that defines the interface.
To make this concrete, here's a scenario where I believe that Go has to create duplicate ones. Suppose that we have four packages, A, B, C, D, and a main package. A defines a concrete type T, B defines an interface I (and perhaps some functions that take it), and both C and D import A and B and statically create B.I instances from A.T instances. Now we use both C and D in our main program.
Package A and B don't know about each other, so neither can define the iface<B.I, A.T> structure. Since C and D may be used by themselves, each must define this separately; they both need it and they have no guaranteed source of it outside themselves. Then when we use both of them together in our main program, we have duplicate definitions of iface<B.I, A.T>, one from each package, so Go must make such duplicates harmless.
The text was updated successfully, but these errors were encountered: