What Is the Difference Between type X Y and type X = Y in Go

`type X Y` creates a new, distinct type that is compatible with `Y` but not interchangeable with it, whereas `type X = Y` creates an alias where `X` and `Y` are exactly the same type.

type X Y creates a new, distinct type that is compatible with Y but not interchangeable with it, whereas type X = Y creates an alias where X and Y are exactly the same type. Use the former when you need type safety and distinct behavior (like custom methods), and the latter when you simply need a shorter or more descriptive name for an existing type.

Here is a practical example showing how the compiler treats them differently:

package main

import "fmt"

// type X Y creates a new type
type MyInt int

// type X = Y creates an alias
type AliasInt = int

func main() {
    var a MyInt = 10
    var b int = 20
    var c AliasInt = 30

    // This fails: MyInt and int are distinct types
    // a = b // Compile error: cannot use b (type int) as type MyInt in assignment

    // This works: AliasInt is exactly int
    c = b 

    fmt.Printf("a: %v, b: %v, c: %v\n", a, b, c)
}

The key distinction lies in type identity. When you define type MyInt int, the Go compiler treats MyInt and int as completely different types. You cannot assign an int to a MyInt variable without an explicit conversion, even though they share the same underlying representation. This is essential for defining domain-specific types (e.g., type Port uint16) to prevent accidental misuse, such as passing a file size where a port number is expected. It also allows you to define methods specifically on MyInt without affecting the built-in int.

Conversely, type AliasInt = int tells the compiler that AliasInt is just another name for int. They are identical in every context. You can assign them freely, pass them to functions expecting the other, and they share the same set of methods. This is useful for readability, such as type Seconds = int to make code self-documenting, or for creating type aliases for complex generic types like type List[T any] = []T.

Choose type X Y when you need to enforce boundaries or extend functionality. Choose type X = Y when you only need a semantic label or a shorthand.