Ming
Ming

Reputation: 972

Why Golang allows circular reference in global scope but not in function scope

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

Answers (1)

Thundercat
Thundercat

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:

  1. 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.

  1. 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

Related Questions