Reputation: 972
As I'm writing DB migrations using gormigrate, I need to define a many-to-many relationship between two structs in a function scope. But in golang 1.19 or 1.18 the following won't compile
package main
import "fmt"
func main() {
type Student struct {
Courses []*Course
// [Error] ./prog.go:7:14: undefined: Course
}
type Course struct {
Students []*Student
}
fmt.Printf("This won't compile")
}
However moving the definitions outside of the function will just work
package main
import "fmt"
type Student struct {
Courses []*Course
}
type Course struct {
Students []*Student
}
func main() {
fmt.Printf("This works")
}
Can try this yourself at https://go.dev/play/p/GI53hhlUTbk
Why is this the case? And how can I make it work in a function scope?
Is there a similar syntax to typedef in C++, so we can declare a struct first and then define it later?
Thanks!
Upvotes: 1
Views: 698
Reputation: 121119
Circular type references are possible in the package block, but not inside a function. The section on Declarations and Scopes in the specification says:
- The scope of an identifier denoting a constant, type, variable, or function (but not method) declared at top level (outside any function) is the package block.
⋮
- The scope of a type identifier declared inside a function begins at the identifier in the TypeSpec and ends at the end of the innermost containing block.
Circular references work at package-level because types declared at package-level are scoped to the entire package block.
The scope of a type declared in a function begins at the declaration, not at the beginning of the containing block. A type cannot reference types declared later in the function because those types are not in scope. It follows that circular type references are not allowed for types declared in a function.
There is not a way to declare the name of a type and later define the type.
Upvotes: 7