package main
import (
"fmt"
"math"
)
// Struct definition
type Point struct {
X, Y float64
}
// Method on a struct (pointer receiver enables mutation)
func (p *Point) Scale(factor float64) {
p.X *= factor
p.Y *= factor
}
// Value receiver (doesn't mutate)
func (p Point) Distance() float64 {
return math.Sqrt(p.X*p.X + p.Y*p.Y)
}
func (p Point) String() string {
return fmt.Sprintf("(%.2f, %.2f)", p.X, p.Y)
}
// Embedding (composition)
type ColoredPoint struct {
Point // embed Point — gets all its methods
Color string
}
// Interface — any type with these methods satisfies it
type Shape interface {
Area() float64
Perimeter() float64
}
type Circle struct{ Radius float64 }
type Rect struct{ Width, Height float64 }
func (c Circle) Area() float64 { return math.Pi * c.Radius * c.Radius }
func (c Circle) Perimeter() float64 { return 2 * math.Pi * c.Radius }
func (r Rect) Area() float64 { return r.Width * r.Height }
func (r Rect) Perimeter() float64 { return 2 * (r.Width + r.Height) }
func printShapeInfo(s Shape) {
fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}
func main() {
p := Point{3, 4}
fmt.Println(p.Distance()) // 5
p.Scale(2)
fmt.Println(p) // (6.00, 8.00)
cp := ColoredPoint{Point: Point{1, 2}, Color: "red"}
fmt.Println(cp.Distance()) // 2.23... (method promoted from Point)
shapes := []Shape{
Circle{Radius: 5},
Rect{Width: 4, Height: 6},
}
for _, s := range shapes {
printShapeInfo(s)
}
}