Go Learning Path - Module 3: Functions, Methods, and Packages
go教程目录
Module 1: Hello World & Basic Concepts
Module 2: Variables, Data Types, and Constants
Module 3: Functions, Methods, and Packages
Module 4: Control Structures (if/else, loops)
Module 5: Arrays, Slices, and Maps Arrays
Module 6: Structs and Interfaces
Module 7: Pointers and Memory Management
Module 8: Concurrency with Goroutines and Channels
Module 9: Error Handling and Defer/Panic/Recover
Module 10: Advanced Topics - Testing and Standard Library
This module explores how to define and use functions, methods, and organize code using packages in Go.
Functions
Functions in Go are defined using the func keyword and can have multiple parameters and return values.
Basic Function Definition
package main
import "fmt"
// Simple function with no parameters or return values
func sayHello() {
fmt.Println("Hello from a function!")
}
// Function with parameters
func greet(name string) {
fmt.Printf("Hello, %s!\n", name)
}
// Function with return value
func add(a int, b int) int {
return a + b
}
// Function with multiple return values
func divide(dividend float64, divisor float64) (float64, error) {
if divisor == 0 {
return 0, fmt.Errorf("division by zero")
}
return dividend / divisor, nil
}
func main() {
sayHello()
greet("Alice")
result := add(5, 3)
fmt.Printf("5 + 3 = %d\n", result)
quotient, err := divide(10, 3)
if err != nil {
fmt.Println("Error:", err)
} else {
fmt.Printf("10 / 3 = %.2f\n", quotient)
}
}
Named Return Values
Go allows you to name return values, which creates variables that hold the return values:
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return // naked return - returns x and y
}
func main() {
a, b := split(17)
fmt.Printf("split(17) = %d, %d\n", a, b) // Output: 7, 10
}
Multiple Parameters with Same Type
When consecutive parameters share the same type, you can omit the type for all but the last:
func addThreeNumbers(x, y, z int) int {
return x + y + z
}
func rectangleArea(width, height float64) float64 {
return width * height
}
Variadic Functions
Functions can accept variable numbers of arguments using ...:
package main
import "fmt"
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
func main() {
fmt.Println(sum(1, 2, 3)) // Output: 6
fmt.Println(sum(1, 2, 3, 4, 5)) // Output: 15
// Pass slice to variadic function
numbers := []int{1, 2, 3, 4, 5}
fmt.Println(sum(numbers...)) // Output: 15 (note the ... to unpack the slice)
}
Anonymous Functions and Closures
Go supports anonymous functions (functions without names) that can capture variables from their surrounding scope (closures):
package main
import "fmt"
func main() {
// Anonymous function assigned to a variable
multiply := func(a, b int) int {
return a * b
}
fmt.Printf("3 * 4 = %d\n", multiply(3, 4))
// Closure example
nextNumber := getSequence()
fmt.Println(nextNumber()) // Output: 1
fmt.Println(nextNumber()) // Output: 2
fmt.Println(nextNumber()) // Output: 3
// Another closure instance
anotherNumber := getSequence()
fmt.Println(anotherNumber()) // Output: 1
}
func getSequence() func() int {
i := 0
return func() int {
i++
return i
}
}
Methods
Methods are functions with a receiver argument. The receiver appears in the function's signature between the func keyword and the method name:
package main
import "fmt"
type Rectangle struct {
width, height float64
}
// Method with pointer receiver
func (r *Rectangle) Scale(factor float64) {
r.width *= factor
r.height *= factor
}
// Method with value receiver
func (r Rectangle) Area() float64 {
return r.width * r.height
}
// Method with value receiver
func (r Rectangle) Perimeter() float64 {
return 2 * (r.width + r.height)
}
func main() {
rect := Rectangle{width: 5, height: 3}
fmt.Printf("Initial area: %.2f\n", rect.Area())
fmt.Printf("Perimeter: %.2f\n", rect.Perimeter())
rect.Scale(2) // Doubles dimensions
fmt.Printf("After scaling: area = %.2f, perimeter = %.2f\n",
rect.Area(), rect.Perimeter())
}
Value Receiver vs Pointer Receiver
-
Use pointer receivers when:
-
You need to modify the receiver
-
The receiver is large (to avoid copying)
-
You want to maintain consistency (if some methods of a type have pointer receivers, the rest should too)
-
-
Use value receivers when:
-
The method doesn't need to modify the receiver
-
The receiver is small and simple
-
Packages
Packages are used to organize and reuse code in Go.
Creating Your Own Package
Create a file called mathutils/mathutils.go:
package mathutils
// Add returns the sum of two integers
func Add(a, b int) int {
return a + b
}
// Subtract returns the difference of two integers
func Subtract(a, b int) int {
return a - b
}
// Multiply returns the product of two integers
func Multiply(a, b int) int {
return a * b
}
// IsEven returns whether a number is even
func IsEven(n int) bool {
return n%2 == 0
}
Then use the package in your main program:
package main
import (
"fmt"
"./mathutils" // Adjust import path as needed
)
func main() {
fmt.Println(mathutils.Add(5, 3)) // Output: 8
fmt.Println(mathutils.Multiply(4, 6)) // Output: 24
fmt.Println(mathutils.IsEven(7)) // Output: false
}
Exported vs Unexported Names
-
Names starting with a capital letter are exported and can be accessed from other packages
-
Names starting with a lowercase letter are unexported (private) and only accessible within the same package
package geometry
// Public function (exported)
func CalculateArea(length, width float64) float64 {
return length * width
}
// Private function (unexported)
func isValidDimension(dimension float64) bool {
return dimension > 0
}
Built-in Packages
Go has an extensive standard library. Some commonly used packages:
package main
import (
"fmt"
"math"
"strings"
"time"
)
func main() {
// math package
fmt.Printf("Square root of 16: %.2f\n", math.Sqrt(16))
fmt.Printf("Ceiling of 3.2: %.0f\n", math.Ceil(3.2))
// strings package
text := "Hello, World!"
fmt.Printf("Lowercase: %s\n", strings.ToLower(text))
fmt.Printf("Contains 'World': %t\n", strings.Contains(text, "World"))
// time package
now := time.Now()
fmt.Printf("Current time: %s\n", now.Format("2006-01-02 15:04:05"))
}
Exercises
-
Write a function that takes a slice of integers and returns the sum, average, minimum, and maximum values.
-
Create a custom type with methods to calculate geometric properties (like area, perimeter).
-
Write a calculator package with functions for addition, subtraction, multiplication, and division.
-
Explore the
fmt,math, andstringspackages and write sample programs using different functions from each.