Project Organization and Style
Internal Boundaries
The internal directory gives Go projects an import boundary enforced by the toolchain.
internal packages
Model internal imports explicitly so package boundaries stay visible.
Internal Boundaries
internal_boundaries.go
Replay: real traced execution (multi-file project)
package main
import (
"fmt"
"strings"
)
func main() {
var importPath = "example.com/shop/internal/config"
ownedPrefix := "example.com/shop/"
usesInternal := strings.Contains(importPath, "/internal/")
owned := strings.HasPrefix(importPath, ownedPrefix)
allowed := !usesInternal || owned
fmt.Println("import=", importPath)
fmt.Println("uses_internal=", usesInternal)
fmt.Println("owned_prefix=", owned)
fmt.Println("allowed=", allowed)
}
package main
import (
"fmt"
"strings"
)
func main() {
var importPath = "example.com/shop/pkg/config"
ownedPrefix := "example.com/shop/"
usesInternal := strings.Contains(importPath, "/internal/")
owned := strings.HasPrefix(importPath, ownedPrefix)
allowed := !usesInternal || owned
fmt.Println("import=", importPath)
fmt.Println("uses_internal=", usesInternal)
fmt.Println("owned_prefix=", owned)
fmt.Println("allowed=", allowed)
}
package main
import (
"fmt"
"strings"
)
func main() {
var importPath = "example.com/other/internal/config"
ownedPrefix := "example.com/shop/"
usesInternal := strings.Contains(importPath, "/internal/")
owned := strings.HasPrefix(importPath, ownedPrefix)
allowed := !usesInternal || owned
fmt.Println("import=", importPath)
fmt.Println("uses_internal=", usesInternal)
fmt.Println("owned_prefix=", owned)
fmt.Println("allowed=", allowed)
}
importPath ← "example.com/shop/internal/config", ownedPrefix ← "example.com/shop/"
8func main() {9 var importPath→ "example.com/shop/internal/config" = "example.com/shop/internal/config" //@importPath="example.com/shop/pkg/config", "example.com/other/internal/config"10 ownedPrefix→ "example.com/shop/" := "example.com/shop/"11 usesInternal→ true := strings.Contains(importPath"example.com/shop/internal/config", "/internal/")12 owned→ true := strings.HasPrefix(importPath"example.com/shop/internal/config", ownedPrefix"example.com/shop/")13 allowed→ true := !usesInternaltrue || ownedtrue1415 fmt.Println("import=", importPath"example.com/shop/internal/config")16 fmt.Println("uses_internal=", usesInternaltrue)17 fmt.Println("owned_prefix=", ownedtrue)18 fmt.Println("allowed=", allowedtrue)19}outputimport= example.com/shop/internal/config uses_internal= true owned_prefix= true allowed= true
importPath ← "example.com/shop/pkg/config", ownedPrefix ← "example.com/shop/"
8func main() {9 var importPath→ "example.com/shop/pkg/config" = "example.com/shop/pkg/config"10 ownedPrefix→ "example.com/shop/" := "example.com/shop/"11 usesInternal→ false := strings.Contains(importPath"example.com/shop/pkg/config", "/internal/")12 owned→ true := strings.HasPrefix(importPath"example.com/shop/pkg/config", ownedPrefix"example.com/shop/")13 allowed→ true := !usesInternalfalse || ownedtrue1415 fmt.Println("import=", importPath"example.com/shop/pkg/config")16 fmt.Println("uses_internal=", usesInternalfalse)17 fmt.Println("owned_prefix=", ownedtrue)18 fmt.Println("allowed=", allowedtrue)19}outputimport= example.com/shop/pkg/config uses_internal= false owned_prefix= true allowed= true
importPath ← "example.com/other/internal/config", ownedPrefix ← "example.com/shop/"
8func main() {9 var importPath→ "example.com/other/internal/config" = "example.com/other/internal/config"10 ownedPrefix→ "example.com/shop/" := "example.com/shop/"11 usesInternal→ true := strings.Contains(importPath"example.com/other/internal/config", "/internal/")12 owned→ false := strings.HasPrefix(importPath"example.com/other/internal/config", ownedPrefix"example.com/shop/")13 allowed→ false := !usesInternaltrue || ownedfalse1415 fmt.Println("import=", importPath"example.com/other/internal/config")16 fmt.Println("uses_internal=", usesInternaltrue)17 fmt.Println("owned_prefix=", ownedfalse)18 fmt.Println("allowed=", allowedfalse)19}outputimport= example.com/other/internal/config uses_internal= true owned_prefix= false allowed= false