函数返回多值

这个在java中是不支持的,得定义一个Tuple去接收,这个功能还是很有用的

  1. package main
  2. import "fmt"
  3. func swap(x, y string) (string, string) {
  4. return y, x
  5. }
  6. func main() {
  7. a, b := swap("Google", "Runoob")
  8. fmt.Println(a, b)
  9. }

函数参数可以是值传递也可以是引用传递

值传递:值传递是指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。

  1. /* 定义相互交换值的函数 */
  2. func swap(x, y int) int {
  3. var temp int
  4. temp = x /* 保存 x 的值 */
  5. x = y /* 将 y 值赋给 x */
  6. y = temp /* 将 temp 值赋给 y*/
  7. return temp;
  8. }
  9. swap(a, b)

引用传递:引用传递是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。

  1. /* 定义交换值函数*/
  2. func swap(x *int, y *int) {
  3. var temp int
  4. temp = *x /* 保持 x 地址上的值 */
  5. *x = *y /* 将 y 值赋给 x */
  6. *y = temp /* 将 temp 值赋给 y */
  7. }
  8. swap(&a, &b) 传入的是ab的值地址

这两个取决于函数定义时的接受参数的类型是不是引用类型

函数作为另一个函数的实参

  1. package main
  2. import (
  3. "fmt"
  4. "math"
  5. )
  6. func main(){
  7. /* 声明函数变量 */
  8. getSquareRoot := func(x float64) float64 {
  9. return math.Sqrt(x)
  10. }
  11. /* 使用函数 */
  12. fmt.Println(getSquareRoot(9))
  13. }

函数作为参数传递,实现回调

  1. package main
  2. import "fmt"
  3. // 声明一个函数类型
  4. type cb func(int) int
  5. func main() {
  6. testCallBack(1, callBack) // 这个是下面声明的callback函数
  7. testCallBack(2, func(x int) int { // 类似java中的匿名函数
  8. fmt.Printf("我是回调,x:%d\n", x)
  9. return x
  10. })
  11. }
  12. func testCallBack(x int, f cb) {
  13. f(x)
  14. }
  15. func callBack(x int) int {
  16. fmt.Printf("我是回调,x:%d\n", x)
  17. return x
  18. }

闭包

Go 语言支持匿名函数,可作为闭包。匿名函数是一个”内联”语句或表达式。匿名函数的优越性在于可以直接使用函数内的变量,不必申明。

以下实例中,我们创建了函数 getSequence() ,返回另外一个函数。该函数的目的是在闭包中递增 i 变量,代码如下:

  1. package main
  2. import "fmt"
  3. func getSequence() func() int {
  4. i:=0
  5. return func() int {
  6. i+=1
  7. return i
  8. }
  9. }
  10. func main(){
  11. /* nextNumber 为一个函数,函数 i 为 0 */
  12. nextNumber := getSequence()
  13. /* 调用 nextNumber 函数,i 变量自增 1 并返回 */
  14. fmt.Println(nextNumber())
  15. fmt.Println(nextNumber())
  16. fmt.Println(nextNumber())
  17. /* 创建新的函数 nextNumber1,并查看结果 */
  18. nextNumber1 := getSequence()
  19. fmt.Println(nextNumber1())
  20. fmt.Println(nextNumber1())
  21. }

执行结果

  1. 1
  2. 2
  3. 3
  4. 1
  5. 2

方法

在Go语言中同时有函数和方法,函数是指不属于任何结构体、类型的方法,也就是说,函数是没有接收者的;而方法是有接收者的,我们说的方法要么是属于一个结构体,要么是属于一个新定义的类型。类比java,java是面向对象的语言,其实只有方法,没有函数这一说,要类比的话,go中的函数可能类似于java中的静态方法,而go中的方法则类似于java中的成员方法。
一个方法就是一个包含了接受者的函数,接受者可以是命名类型或者结构体类型的一个值或者是一个指针。所有给定类型的方法属于该类型的方法集。

语法格式如下:

  1. func (variable_name variable_data_type) function_name() [return_type]{
  2. /* 函数体*/
  3. }

方法的声明和函数类似,他们的区别是:方法在定义的时候,会在func和方法名之间增加一个参数,这个参数就是接收者,这样我们定义的这个方法就和接收者绑定在了一起,称之为这个接收者的方法。

  1. package main
  2. import (
  3. "fmt"
  4. )
  5. /* 定义结构体 */
  6. type Circle struct {
  7. radius float64
  8. }
  9. func main() {
  10. var c1 Circle
  11. c1.radius = 10.00
  12. fmt.Println("圆的面积 = ", c1.getArea())
  13. }
  14. //该 method 属于 Circle 类型对象中的方法
  15. func (c Circle) getArea() float64 {
  16. //c.radius 即为 Circle 类型对象中的属性
  17. return 3.14 * c.radius * c.radius
  18. }

Go 没有面向对象,而我们知道常见的 Java。

C++ 等语言中,实现类的方法做法都是编译器隐式的给函数加一个 this 指针,而在 Go 里,这个 this 指针需要明确的申明出来,其实和其它 OO 语言并没有很大的区别。

在 C++ 中是这样的:

  1. class Circle {
  2. public:
  3. float getArea() {
  4. return 3.14 * radius * radius;
  5. }
  6. private:
  7. float radius;
  8. }
  9. // 其中 getArea 经过编译器处理大致变为
  10. float getArea(Circle *const c) {
  11. ...
  12. }

在Go中则是如下,在这样的实现中,其实就省略掉了this指针:

  1. func (c Circle) getArea() float64 {
  2. //c.radius 即为 Circle 类型对象中的属性
  3. return 3.14 * c.radius * c.radius
  4. }