Go Structs and Methods

Back to Go Index

Struct

ประกาศชุดกลุ่มข้อมูล

type course struct {
	name       string
	instructor string
	price      float64
}
 
func main() {
	c1 := course{
		name:       "Golang",
		instructor: "John Doe",
		price:      10.99,
	}
	println(c.name)
}

Methods

การเรียกใช้ function โดยผูกกับ struct หรือ non-struct ก็ได้ โดยอาศัย Receiver

การใช้แบบ function

func discount(c course, d float64) float64 {
	p := c.price - d
	fmt.Println("Discount:", p)
	return p
}
 
func main() {
	c := course{"Go Fundamentals", "Nigel Poulton", 11.99}
	fmt.Printf("course: %+v\n", c)
 
	d := discount(c, 2.99)
	fmt.Println("discount price:", d)
}

การใช้แบบ method

func (c course) discount(d float64) float64 { // Reciever
	p := c.price - d
	fmt.Println("Discount:", p)
	return p
}
 
func main() {
	c := course{"Go Fundamentals", "Nigel Poulton", 11.99}
	fmt.Printf("course: %+v\n", c)
 
	d := c.discount(2.99) // Change
	fmt.Println("discount price:", d)
}

Method with Pointer Receiver

ตัวอย่างการสร้าง method addVote() เพิ่มค่า rating เข้าไปใน slice votes ของ struct movie

type movie struct {
	title       string
	year        int
	rating      float32
	votes       []float64
	genres      []string
	isSuperHero bool
}
 
func (m *movie) addVote(rating float64) {
	m.votes = append(m.votes, rating)
}
 
func main() {
	eg := &movie{
		title:       "Avengers: Endgame",
		year:        2019,
		rating:      8.4,
		votes:       []float64{7, 8, 9, 10},
		genres:      []string{"Action", "Drama"},
		isSuperHero: true,
	}
	fmt.Println("votes:", eg.votes)
 
	eg.addVote(8)
	fmt.Println("votes:", eg.votes)
 
	// votes: [7 8 9 10]
	// votes: [7 8 9 10 8]
}

Value vs Pointer Returns

ความแตกต่างระหว่าง struct ที่ return ปกติ กับเป็น pointer

type Person struct {
	Name string
	Age  int
}
 
// Approach 1: Returning Person by value (cannot modify)
func NewPersonImmutable(name string, age int) Person {
	return Person{
		Name: name,
		Age:  age,
	}
}
 
// Approach 2: Returning *Person (can modify)
func NewPersonMutable(name string, age int) *Person {
	return &Person{
		Name: name,
		Age:  age,
	}
}
 
func main() {
	// Approach 1: Immutable
	p1 := NewPersonImmutable("John", 25)
	p1.Age = 30 // Cannot modify directly
 
	// Approach 2: Mutable
	p2 := NewPersonMutable("Jane", 25)
	p2.Age = 30 // Can modify directly
 
	fmt.Println(p1) // Output: {John 25}
	fmt.Println(p2) // Output: &{Jane 30}
}

Struct Embedding

Embedding Struct by Value

type Animal struct {
	Name     string
	Sound    string
	IsMammal bool
}
 
type CowA struct {
	Animal
}
 
type CowB struct {
	Animal
}
 
func main() {
	cow := Animal{
		Name:     "Cow",
		Sound:    "Moo",
		IsMammal: true,
	}
 
	cowA := CowA{
		Animal: cow,
	}
 
	cowB := CowB{
		Animal: cow,
	}
 
	// Modifying the value of the struct
	cowA.Sound = "Mooooooo"
	fmt.Println("cowA:", cowA.Sound) // Mooooooo
	fmt.Println("cowB:", cowB.Sound) // Moo
}

Embedding Struct by Pointer

Student struct ที่มี field University เป็น *University (pointer) แปลว่าการเปลี่ยนแปลงค่าของ instance หนึ่งที่มี reference ถึงของชิ้นเดียวกันจะเปลี่ยนตามไปด้วย

type University struct {
	Name     string
	Location string
}
 
type Student struct {
	Name       string
	Age        int
	University *University
}
 
func main() {
	university := &University{
		Name:     "ABC University",
		Location: "City XYZ",
	}
 
	student1 := Student{
		Name:       "John",
		Age:        20,
		University: university,
	}
 
	student2 := Student{
		Name:       "Alice",
		Age:        22,
		University: university,
	}
 
	student1.University.Name = "XYZ University"
 
	fmt.Println(student1.University.Name) // Output: XYZ University
	fmt.Println(student2.University.Name) // Output: XYZ University
}

Comparison: Value vs Pointer Embedding

type Animal struct {
	Name     string
	Sound    string
	IsMammal bool
}
 
type DuckA struct {
	*Animal
}
 
type DuckB struct {
	*Animal
}
 
func main() {
	duck := &Animal{
		Name:     "Duck",
		Sound:    "Quack",
		IsMammal: false,
	}
 
	duckA := DuckA{
		Animal: duck,
	}
 
	duckB := DuckB{
		Animal: duck,
	}
 
	// Modifying the value of the pointer
	duckA.Sound = "Quackkkkkk"
	fmt.Println("duckA:", duckA.Sound) // Quackkkkkk
	fmt.Println("duckB:", duckB.Sound) // Quackkkkkk
}

Related: