• In Go, type is a keyword used to define a new named type based on some underlying type (a struct, an existing primitive, an interface, a function signature, etc).

    type User struct {      // a struct type
    	Name string
    }
    
    type Age int            // a named type based on int
    
    type Shape interface {  // an interface type
    	Area() float64 // method with float return
    }
    
    type Handler func(w http.ResponseWriter, r *http.Request) // a function type
    
  • In short: type is how you tell Go "here's a new named shape of data (or contract) that the rest of my code can refer to by this name."

  • It's not a variable declaration, it declares a type (a blueprint), not a value. You still need var or := to create an actual value of that type: var u User or u := User{Name: "Jo"}.

    type User struct {
        Name string
    }
    
    // This just declares the shape — no value exists yet:
    // type User struct { Name string }
    
    // These actually create values:
    var u User
    u2 := User{Name: "Jo"}
    
  • Struct types are the most common use, grouping related fields together into one named shape (type User struct {...}), like collecting FirstName, Email, and Password into a single User instead of passing them around as separate variables.

    type User struct {
        FirstName string
        Email     string
        Password  string
    }
    
    func createUser(u User) {
        fmt.Println("Creating user:", u.FirstName, u.Email)
    }
    
    // Instead of: createUser(firstName, email, password string)
    u := User{FirstName: "Jo", Email: "[email protected]", Password: "secret"}
    createUser(u)
    
  • Type aliasing over primitives (type Age int) creates a distinct type that the compiler treats as separate from plain int, even though it behaves like one underneath. This is a type-safety tool: it stops you from accidentally passing an int where an Age was expected, catching mistakes the compiler would otherwise let slide.

    type Age int
    
    func greet(a Age) {
        fmt.Println("You are", a, "years old")
    }
    
    func main() {
        var a Age = 30
        greet(a) // works fine
    
        var i int = 25
        greet(i) // compile error: cannot use i (type int) as type Age
    }
    
  • Interface types (type Shape interface {...}) declare a contract of method signatures rather than any concrete data.

    type Shape interface {
        Area() float64
    }
    
    type Circle struct {
        Radius float64
    }
    
    func (c Circle) Area() float64 {
        return 3.14159 * c.Radius * c.Radius
    }
    
    func printArea(s Shape) {
        fmt.Println("Area:", s.Area())
    }
    
    // Circle satisfies Shape just by having an Area() method
    printArea(Circle{Radius: 5})
    
  • Once a type is declared, you can attach methods to it using a receiver: func (u User) SayHi() {}. This works for struct types and named primitive types alike (not for interfaces, methods on interfaces are the required contract itself, not something you attach afterward).