网站建设使用的什么语言龙岗这边哪里有教做网站的
网站建设使用的什么语言,龙岗这边哪里有教做网站的,网站推广途径方法,wordpress 农场主题目录
1. 函数#xff08;Function#xff09;
1.1 函数定义
无参数无返回值
有参数
有返回值
多返回值
命名返回值
1.2 参数传递
1.3 可变参数
1.4 函数作为一等公民
函数赋值给变量
函数作为参数#xff08;回调函数#xff09;
函数作为返回值#xff08;闭…目录1. 函数Function1.1 函数定义无参数无返回值有参数有返回值多返回值命名返回值1.2 参数传递1.3 可变参数1.4 函数作为一等公民函数赋值给变量函数作为参数回调函数函数作为返回值闭包1.5 匿名函数1.6 闭包2. 方法Method2.1 方法定义2.2 接收者类型值 vs 指针2.3 方法与函数的区别2.4 方法集2.5 为任意类型添加方法2.6 方法继承与重写3. 总结欢迎回到Go语言入门系列在上一篇文章中我们学习了Go的复合数据类型包括数组、切片、映射和结构体这些让我们能够组织和存储复杂的数据。但数据还需要操作操作数据的行为就封装在函数和方法中。函数是Go程序的基本组成单元而方法则是与特定类型关联的函数。今天我们将深入探讨Go中的函数和方法理解它们的定义、特性以及如何正确使用。1. 函数Function函数是一段完成特定任务的代码块可以接受输入参数并返回输出返回值。在Go中函数是“一等公民”可以像变量一样被传递和赋值。1.1 函数定义Go使用func关键字定义函数基本语法如下func 函数名(参数列表) 返回值列表 { // 函数体 return 值 }无参数无返回值func sayHello() { fmt.Println(Hello, Go!) }有参数func greet(name string) { fmt.Printf(Hello, %s!\n, name) }有返回值func add(a int, b int) int { return a b }如果多个参数类型相同可以省略前面的类型func add(a, b int) int { // a 和 b 都是 int return a b }多返回值Go函数支持返回多个值这是Go语言的一大特色常用于返回结果和错误信息。func divide(a, b float64) (float64, error) { if b 0 { return 0, errors.New(除数不能为零) } return a / b, nil } func main() { result, err : divide(10, 2) if err ! nil { fmt.Println(出错, err) } else { fmt.Println(结果, result) } }命名返回值可以为返回值指定名称就像变量一样。在函数体内可以直接给这些变量赋值然后通过空的return返回。func split(sum int) (x, y int) { x sum * 4 / 9 y sum - x return // 裸返回返回 x 和 y 的当前值 }注意命名返回值应谨慎使用尤其在函数较长时裸返回可能降低代码可读性。1.2 参数传递Go语言中函数参数都是值传递即传递的是实参的副本。这意味着在函数内部修改参数不会影响原变量除非传递的是指针。func zeroVal(val int) { val 0 } func zeroPtr(ptr *int) { *ptr 0 } func main() { x : 5 zeroVal(x) fmt.Println(x) // 5未改变 zeroPtr(x) fmt.Println(x) // 0改变了 }对于切片、映射、通道、接口等引用类型它们本身包含指向底层数据的指针所以函数内对元素的修改会影响原变量但对切片本身如长度、容量的修改不会影响原切片除非使用指针。这需要特别留意。1.3 可变参数Go支持可变参数使用...表示。可变参数必须是函数的最后一个参数在函数内部作为切片使用。func sum(nums ...int) int { total : 0 for _, num : range nums { total num } return total } func main() { fmt.Println(sum(1, 2)) // 3 fmt.Println(sum(1, 2, 3, 4)) // 10 // 也可以传入切片需要展开 nums : []int{1, 2, 3, 4, 5} fmt.Println(sum(nums...)) // 15 }1.4 函数作为一等公民在Go中函数也是类型可以赋值给变量作为参数传递给其他函数或者作为返回值。函数赋值给变量func double(x int) int { return x * 2 } func main() { var f func(int) int double fmt.Println(f(5)) // 10 }函数作为参数回调函数func apply(nums []int, f func(int) int) []int { result : make([]int, len(nums)) for i, v : range nums { result[i] f(v) } return result } func main() { nums : []int{1, 2, 3, 4} doubled : apply(nums, func(x int) int { return x * 2 }) fmt.Println(doubled) // [2 4 6 8] }函数作为返回值闭包func adder() func(int) int { sum : 0 return func(x int) int { sum x return sum } } func main() { pos, neg : adder(), adder() for i : 0; i 5; i { fmt.Println(pos(i), neg(-2*i)) } }1.5 匿名函数匿名函数没有函数名可以直接定义并调用或者赋值给变量。func main() { // 定义并调用 func(msg string) { fmt.Println(msg) }(hello) // 赋值给变量 greet : func(name string) { fmt.Printf(Hi, %s\n, name) } greet(Tom) }1.6 闭包闭包是一个函数“捕获”了其外部作用域的变量。上述adder函数返回的匿名函数就是一个闭包它“记住”了sum变量。闭包的特性使它在函数式编程中非常有用但也要注意变量捕获可能导致意料之外的副作用。2. 方法Method方法是与特定类型关联的函数。Go没有类但可以通过为类型定义方法来模拟面向对象的行为。方法的接收者可以是值或指针。2.1 方法定义方法定义的语法与函数类似只是在func关键字和函数名之间增加了接收者参数。type Rectangle struct { Width, Height float64 } // 值接收者方法 func (r Rectangle) Area() float64 { return r.Width * r.Height } // 指针接收者方法 func (r *Rectangle) Scale(factor float64) { r.Width * factor r.Height * factor }调用方法时使用点号.func main() { rect : Rectangle{Width: 10, Height: 5} fmt.Println(面积:, rect.Area()) // 调用值接收者方法 rect.Scale(2) // 调用指针接收者方法 fmt.Println(缩放后面积:, rect.Area()) }2.2 接收者类型值 vs 指针值接收者方法操作的是接收者的副本如果接收者是结构体会复制整个结构体。方法内部对接收者的修改不会影响原值。适用于不需要修改接收者或接收者很小复制成本低的场景。指针接收者方法操作的是接收者的指针可以修改原值。同时可以避免复制大结构体提高效率。选择指南如果方法需要修改接收者必须使用指针接收者。如果接收者是大型结构体或需要避免复制开销建议使用指针接收者。如果接收者是切片、映射等引用类型值接收者可能也能修改内容因为底层数据相同但无法修改接收者本身如重新分配切片。一般对于引用类型如果需要修改接收者本身如重置切片仍需要指针接收者。如果接收者是基本类型、小结构体且不需要修改可以使用值接收者。2.3 方法与函数的区别函数不依赖于任何类型直接调用方法必须依附于类型通过接收者调用。方法可以调用同一类型下的其他方法包括私有字段函数则不能直接访问类型的未导出字段。方法可以重名不同接收者类型函数在同一包内不能重名。2.4 方法集方法集定义了一个类型可以调用的方法集合。规则如下重要但容易混淆对于类型T方法集包含所有接收者为T的方法。对于类型*T方法集包含所有接收者为*T和T的方法。换句话说值类型T的变量只能调用接收者为T的方法值接收者不能直接调用接收者为*T的方法指针接收者。但Go会隐式地取地址不当调用一个值类型变量的指针接收者方法时Go编译器会自动取地址所以t.Method()其中Method有指针接收者编译器会转换为(t).Method()前提是变量是可寻址的。所以通常我们感觉值变量也可以调用指针接收者方法但这是语法糖不是方法集的定义。指针类型*T的变量可以调用接收者为*T和T的方法。示例type MyInt int func (m MyInt) ValueMethod() { fmt.Println(Value method) } func (m *MyInt) PointerMethod() { fmt.Println(Pointer method) } func main() { var v MyInt 10 v.ValueMethod() // OK v.PointerMethod() // OK (编译器自动取地址) var p *MyInt v p.ValueMethod() // OK (编译器自动解引用) p.PointerMethod() // OK }但在接口实现时方法集规则是严格的一个类型实现某个接口必须包含接口所需的所有方法此时编译器检查的是方法集不会自动转换。例如type Stringer interface { String() string } type MyType struct{} func (m MyType) String() string { // 值接收者 return hello } func main() { var s Stringer MyType{} // OK var s2 Stringer MyType{} // OK因为 *MyType 的方法集包含值接收者方法 }如果方法是指针接收者则只有*MyType实现了接口MyType没有实现。func (m *MyType) String() string { return hello } func main() { var s Stringer MyType{} // OK // var s2 Stringer MyType{} // 编译错误MyType does not implement Stringer }2.5 为任意类型添加方法Go允许为任何自定义类型添加方法不仅仅是结构体。例如可以为基本类型别名添加方法。type Counter int func (c *Counter) Increment() { *c } func (c Counter) String() string { return fmt.Sprintf(Count: %d, c) } func main() { var c Counter 5 c.Increment() fmt.Println(c.String()) // Count: 6 }2.6 方法继承与重写Go没有传统的继承但可以通过内嵌结构体实现类似的效果。当内嵌一个类型时外部类型会自动获得内嵌类型的所有方法就好像这些方法属于外部类型一样。type Animal struct { Name string } func (a Animal) Speak() { fmt.Println(a.Name, makes a sound) } type Dog struct { Animal // 内嵌 Breed string } func main() { d : Dog{Animal: Animal{Name: Buddy}, Breed: Golden} d.Speak() // Buddy makes a soundDog 获得了 Animal 的方法 }如果Dog也定义了同名方法则内嵌类型的方法会被“屏蔽”可以通过d.Animal.Speak()调用。func (d Dog) Speak() { fmt.Println(d.Name, barks) } func main() { d : Dog{Animal: Animal{Name: Buddy}, Breed: Golden} d.Speak() // Buddy barks d.Animal.Speak() // Buddy makes a sound }这为Go提供了一种组合优于继承的代码复用方式。3. 总结今天我们学习了Go中的函数和方法函数定义、多返回值、值传递、可变参数、函数作为一等公民闭包、匿名函数。方法接收者值/指针、方法集规则、为任意类型添加方法、通过内嵌实现方法复用。函数和方法是Go程序逻辑组织的核心灵活运用它们能让代码更清晰、更模块化。下一篇文章我们将探讨Go的接口理解如何定义行为契约敬请期待练习建议编写一个函数接受一个整数切片返回其最大值和最小值。编写一个函数makeMult返回一个闭包该闭包将输入乘以一个因子由makeMult的参数指定。定义一个Circle结构体半径为其添加Area()面积和Scale(float64)缩放半径方法分别使用值接收者和指针接收者观察差异。创建一个String方法接收者为值的结构体测试将其赋值给fmt.Stringer接口时值类型和指针类型的行为。定义两个结构体Engine有Start()方法和Car内嵌Engine调用Car的Start()并尝试重写该方法。如果你有任何疑问或想分享你的代码欢迎在评论区留言我们下期见。