package main

import "fmt"

type Kotak[T any] struct {
	Isi T
}

// Method memakai type parameter milik receiver — sah sejak Go 1.18.
func (k Kotak[T]) Cetak(label string) {
	fmt.Printf("%s: %v\n", label, k.Isi)
}

// Method generik dengan type parameter sendiri — baru di Go 1.27.
func (k Kotak[T]) Ubah[U any](f func(T) U) Kotak[U] {
	return Kotak[U]{Isi: f(k.Isi)}
}

func main() {
	asli := Kotak[int]{Isi: 21}
	asli.Cetak("asli")

	// U tersimpulkan sebagai string dari argumen fungsi.
	teks := asli.Ubah(func(n int) string { return fmt.Sprintf("nilai %d", n) })
	teks.Cetak("hasil")

	ganda := asli.Ubah(func(n int) float64 { return float64(n) * 2 })
	ganda.Cetak("ganda")
}
