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!