Go语言函数:从基础到高级应用实践
一、函数定义基础语法
// 基础函数定义模板
func functionName(参数列表) 返回值类型 {
// 函数体
}
// 带参数的函数示例
func add(x int, y int) int {
return x + y
}
// 参数类型简写(相同类型参数)
func multiply(a, b int) int {
return a * b
}
// 无参数无返回值函数
func printHello() {
fmt.Println("Hello, Go!")
}
关键知识点:
- 参数列表支持类型后置语法
- 返回值类型可以是单个或多个
- 支持命名返回值(后面详解)
- 函数首字母大小写决定访问权限
二、函数调用方式详解
2.1 基本调用方式
sum := add(3, 5)
fmt.Println(sum) // 输出8
printHello() // 直接调用无返回值函数
2.2 忽略返回值
// 使用空白标识符忽略返回值
_, err := os.Open("file.txt")
if err != nil {
log.Fatal(err)
}
2.3 链式调用
// 连续调用示例
strings.NewReader("hello").Read(make([]byte, 5))
三、多返回值深度解析
3.1 基本多返回值
func swap(a, b string) (string, string) {
return b, a
}
x, y := swap("hello", "world")
3.2 命名返回值
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return // 裸返回
}
a, b := split(100)
3.3 错误处理模式
func OpenFile(path string) (*os.File, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
return file, nil
}
四、可变参数函数
func sum(nums ...int) int {
total := 0
for _, num := range nums {
total += num
}
return total
}
// 使用示例
fmt.Println(sum(1,2,3)) // 6
fmt.Println(sum([]int{4,5,6}...)) // 切片展开
高级用法:
func logger(prefix string, values ...interface{}) {
fmt.Printf("[%s] %v\n", prefix, values)
}
logger("DEBUG", "user login", 200, time.Now())
五、匿名函数与闭包
5.1 匿名函数定义
// 立即执行函数
func() {
fmt.Println("立即执行匿名函数")
}()
// 赋值给变量
square := func(x int) int {
return x * x
}
fmt.Println(square(5)) // 25
5.2 闭包实践
// 累加器生成器
func adder() func(int) int {
sum := 0
return func(x int) int {
sum += x
return sum
}
}
a := adder()
fmt.Println(a(1)) // 1
fmt.Println(a(2)) // 3
fmt.Println(a(10)) // 13
实际应用场景:
- 中间件链
- 状态封装
- 延迟计算
- 并发安全访问
六、错误处理最佳实践
6.1 错误处理模式
func ReadConfig(path string) (Config, error) {
file, err := os.Open(path)
if err != nil {
return Config{}, fmt.Errorf("打开配置文件失败: %w", err)
}
defer file.Close()
// 解析配置...
return config, nil
}
6.2 自定义错误类型
type APIError struct {
Code int
Message string
Details interface{}
}
func (e *APIError) Error() string {
return fmt.Sprintf("%d: %s", e.Code, e.Message)
}
func NewAPIError(code int, msg string) *APIError {
return &APIError{
Code: code,
Message: msg,
}
}
6.3 panic和recover
func safeDivision(a, b int) (result int, err error) {
defer func() {
if r := recover(); r != nil {
err = fmt.Errorf("运行时错误: %v", r)
}
}()
if b == 0 {
panic("除零错误")
}
return a / b, nil
}
七、高阶函数应用
7.1 函数作为参数
func filter(numbers []int, condition func(int) bool) []int {
var result []int
for _, n := range numbers {
if condition(n) {
result = append(result, n)
}
}
return result
}
// 使用示例
numbers := []int{1,2,3,4,5}
evens := filter(numbers, func(n int) bool {
return n%2 == 0
})
7.2 函数作为返回值
func makeMultiplier(factor int) func(int) int {
return func(x int) int {
return x * factor
}
}
double := makeMultiplier(2)
triple := makeMultiplier(3)
fmt.Println(double(5)) // 10
fmt.Println(triple(5)) // 15
八、性能优化技巧
8.1 避免闭包滥用
// 不推荐写法(频繁创建闭包)
func process(data []int) {
for _, v := range data {
go func() {
fmt.Println(v) // 闭包捕获循环变量问题
}()
}
}
// 推荐写法
func processOptimized(data []int) {
for _, v := range data {
go func(val int) {
fmt.Println(val)
}(v)
}
}
8.2 内联优化
// 简单函数会被编译器自动内联
func max(a, b int) int {
if a > b {
return a
}
return b
}
// 调用处会被优化为直接比较操作
result := max(x, y)
九、测试驱动开发示例
// math_test.go
func TestAdd(t *testing.T) {
testCases := []struct {
a, b int
want int
}{
{2, 3, 5},
{-1, 1, 0},
{0, 0, 0},
}
for _, tc := range testCases {
got := add(tc.a, tc.b)
if got != tc.want {
t.Errorf("add(%d, %d) = %d; want %d", tc.a, tc.b, got, tc.want)
}
}
}
十、实战项目案例:中间件实现
type Middleware func(http.HandlerFunc) http.HandlerFunc
func Logger() Middleware {
return func(next http.HandlerFunc) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
defer func() {
log.Printf(
"%s %s %v",
r.Method,
r.URL.Path,
time.Since(start),
)
}()
next(w, r)
}
}
}
func Chain(f http.HandlerFunc, middlewares ...Middleware) http.HandlerFunc {
for _, m := range middlewares {
f = m(f)
}
return f
}
// 使用示例
func main() {
handler := func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello World"))
}
http.HandleFunc("/", Chain(handler, Logger()))
http.ListenAndServe(":8080", nil)
}
正文到此结束
相关文章
热门推荐
评论插件初始化中...