📖 Golang Toàn tập - Functions, Methods và Interfaces
75 phút

Functions, Methods và Interfaces trong Go

Functions

Function cơ bản

func add(a, b int) int {
    return a + b
}

// Multiple return values
func divide(a, b float64) (float64, error) {
    if b == 0 {
        return 0, fmt.Errorf("division by zero")
    }
    return a / b, nil
}

// Named return values
func split(sum int) (x, y int) {
    x = sum * 4 / 9
    y = sum - x
    return
}

Variadic functions

func sum(nums ...int) int {
    total := 0
    for _, n := range nums {
        total += n
    }
    return total
}

sum(1, 2, 3)
nums := []int{1, 2, 3}
sum(nums...)

Closures

func counter() func() int {
    count := 0
    return func() int {
        count++
        return count
    }
}

c := counter()
c() // 1
c() // 2

Function types

type MathFunc func(a, b int) int

func compute(fn MathFunc, a, b int) int {
    return fn(a, b)
}

result := compute(func(a, b int) int { return a + b }, 3, 4)

Methods

Method với value receiver

type Rectangle struct {
    Width  float64
    Height float64
}

func (r Rectangle) Area() float64 {
    return r.Width * r.Height
}

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

Method với pointer receiver

func (r *Rectangle) Scale(factor float64) {
    r.Width *= factor
    r.Height *= factor
}

Method trên custom types

type Celsius float64

func (c Celsius) ToFahrenheit() Fahrenheit {
    return Fahrenheit(c*9/5 + 32)
}

type Fahrenheit float64

Interfaces

Interface cơ bản

type Shape interface {
    Area() float64
    Perimeter() float64
}

func PrintShapeInfo(s Shape) {
    fmt.Printf("Area: %.2f, Perimeter: %.2f\n", s.Area(), s.Perimeter())
}

Empty interface

func describe(i interface{}) {
    fmt.Printf("(%v, %T)\n", i, i)
}

describe(42)
describe("hello")
describe(true)

Type assertions

var i interface{} = "hello"

s, ok := i.(string)
if ok {
    fmt.Println("String:", s)
}

// Type switch
switch v := i.(type) {
case string:
    fmt.Println("String:", v)
case int:
    fmt.Println("Int:", v)
default:
    fmt.Println("Unknown type")
}

Common interfaces

// Stringer
type Stringer interface {
    String() string
}

func (u User) String() string {
    return fmt.Sprintf("%s <%s>", u.Name, u.Email)
}

// Error
type error interface {
    Error() string
}

Error Handling

Custom errors

type ValidationError struct {
    Field string
    Msg   string
}

func (e *ValidationError) Error() string {
    return fmt.Sprintf("%s: %s", e.Field, e.Msg)
}

func Validate(user User) error {
    if user.Email == "" {
        return &ValidationError{
            Field: "email",
            Msg:   "email is required",
        }
    }
    return nil
}

Error wrapping (Go 1.13+)

import "errors"

func process() error {
    err := doSomething()
    if err != nil {
        return fmt.Errorf("process failed: %w", err)
    }
    return nil
}

// Check
if errors.Is(err, ErrNotFound) {
    // handle not found
}

var validationErr *ValidationError
if errors.As(err, &validationErr) {
    fmt.Println(validationErr.Field)
}

Bài tập thực hành

Hãy tạo một interface cho hình học và implement các hình khác nhau!

📝 Bài tập (1)

  1. Tạo interface Shape và implement các hình