Methods

Method adalah fungsi yang terikat dengan tipe data tertentu. Di Go, kita bisa menambahkan method ke tipe data apapun yang didefinisikan dalam package yang sama.

Contoh Masalah

Bagaimana cara:

  1. Menambahkan behavior ke tipe data
  2. Membuat object-oriented like programming
  3. Mengorganisir fungsi yang berhubungan

Penyelesaian

package main

import (
    "fmt"
    "math"
)

// 1. Struct dengan methods
type Rectangle struct {
    Width  float64
    Height float64
}

// Method dengan value receiver
func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

// Method dengan pointer receiver
func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

// 2. Method untuk tipe data dasar
type MyFloat float64

func (f MyFloat) Abs() float64 {
    if f < 0 {
        return float64(-f)
    }
    return float64(f)
}

// 3. Interface implementation dengan method
type Shape interface {
    Area() float64
    Perimeter() float64
}

// Implementasi interface untuk Rectangle
func (r Rectangle) Perimeter() float64 {
    return 2 * (r.Width + r.Height)
}

// Circle dengan method
type Circle struct {
    Radius float64
}

func (c Circle) Area() float64 {
    return math.Pi * c.Radius * c.Radius
}

func (c Circle) Perimeter() float64 {
    return 2 * math.Pi * c.Radius
}

// 4. Method chaining
type StringBuilder struct {
    str string
}

func (sb *StringBuilder) Append(s string) *StringBuilder {
    sb.str += s
    return sb
}

func (sb *StringBuilder) AppendLine(s string) *StringBuilder {
    sb.str += s + "\n"
    return sb
}

func (sb StringBuilder) String() string {
    return sb.str
}

func main() {
    // Contoh 1: Rectangle methods
    rect := Rectangle{Width: 10, Height: 5}
    fmt.Printf("Rectangle: %+v\n", rect)
    fmt.Printf("Area: %.2f\n", rect.Area())
    fmt.Printf("Perimeter: %.2f\n", rect.Perimeter())

    // Menggunakan pointer method
    rect.Scale(2)
    fmt.Printf("\nSetelah scaling: %+v\n", rect)
    fmt.Printf("Area baru: %.2f\n", rect.Area())

    // Contoh 2: Method pada tipe data dasar
    f := MyFloat(-42)
    fmt.Printf("\nAbsolute value: %.2f\n", f.Abs())

    // Contoh 3: Interface dan method
    var shapes []Shape
    shapes = append(shapes, Rectangle{Width: 3, Height: 4})
    shapes = append(shapes, Circle{Radius: 5})

    fmt.Printf("\nCalculating areas:\n")
    for _, shape := range shapes {
        fmt.Printf("Area: %.2f\n", shape.Area())
        fmt.Printf("Perimeter: %.2f\n", shape.Perimeter())
    }

    // Contoh 4: Method chaining
    sb := &StringBuilder{}
    result := sb.Append("Hello").
        AppendLine(" World!").
        Append("How ").
        AppendLine("are you?").
        String()

    fmt.Printf("\nStringBuilder result:\n%s", result)

    // Contoh 5: Value vs Pointer receiver
    r1 := Rectangle{Width: 2, Height: 3}
    r2 := r1 // Copy value

    r1.Scale(2) // Only affects r1
    fmt.Printf("\nValue vs Pointer receiver:\n")
    fmt.Printf("r1: %+v\n", r1)
    fmt.Printf("r2: %+v\n", r2)
}

Penjelasan Kode

  1. Method Declaration

    • Fungsi dengan receiver
    • Value vs pointer receiver
    • Dapat ditambahkan ke tipe apapun
  2. Receiver Types

    • Value receiver: mendapat copy
    • Pointer receiver: dapat mengubah nilai
    • Pilih sesuai kebutuhan
  3. Method vs Function

    • Method terikat dengan tipe
    • Lebih object-oriented
    • Lebih mudah dibaca

Output

Rectangle: {Width:10 Height:5}
Area: 50.00
Perimeter: 30.00

Setelah scaling: {Width:20 Height:10}
Area baru: 200.00

Absolute value: 42.00

Calculating areas:
Area: 12.00
Perimeter: 14.00
Area: 78.54
Perimeter: 31.42

StringBuilder result:
Hello World!
How are you?

Value vs Pointer receiver:
r1: {Width:4 Height:6}
r2: {Width:2 Height:3}

Tips

  • Gunakan pointer receiver untuk mengubah state
  • Gunakan value receiver untuk operasi read-only
  • Konsisten dalam penggunaan receiver type
  • Method membuat code lebih modular
  • Manfaatkan method chaining untuk fluent interface