编辑代码

package main
import "fmt"
/*
Go语言中,函数的基本组成为:关键字 func、函数名、参数列表、返回值、函数体和返回语句,每一个程序都包含很多的函数,函数是基本的代码块。
Go语言是编译型语言,所以函数编写的顺序是无关紧要的
鉴于可读性的需求,最好把 main() 函数写在文件的前面,其他函数按照一定逻辑顺序进行编写(例如函数被调用的顺序)
*/
func main () {
    /*
    • 支持不定变参。
    • 支持多返回值。
    • 支持命名返回参数。 
    • 支持匿名函数和闭包。
    • 函数也是一种类型,一个函数可以赋值给变量。
    • 不支持 嵌套 (nested) 一个包不能有两个名字一样的函数。
    • 不支持 重载 (overload) 
    • 不支持 默认参数 (default parameter)。
    */

    /* 
    函数的调用  函数可以多次调用
    在函数调用时参数为实际参数(实参) 有具体的值 用来给形式参数(形参) 传递数据
   */
    var a, b int =10,20
    add(a, b)
    add(2,4)

    //引用传参:指在调用函数时将实际参数的地址传递到函数中,在函数中对参数所进行的修改,将影响到实际参数
    fmt.Println(a, b)
    swap(&a,&b)
    fmt.Println(a, b)
    /*
    注意1:值传递或者引用传递,传递给函数的都是变量的副本,值传递是值的拷贝。引用传递是地址的拷贝,当然地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
    注意2:map、slice、chan、指针、interface默认以引用的方式传递
    */

    //任意类型的不定参数
    sum := test("sum:",1,2,3)
    println(sum)

    //使用 slice 对象做变参时,必须展开
    s :=[]int{1,2,3,4}
    res :=testSlice("sum: %d", s...)// slice... 展开slice
    println(res)

    /*go函数返回值
    1."_"标识符,用来忽略函数的某个返回值
    2.Go 的返回值可以被命名,并且就像在函数体开头声明的变量那样使用
    3.没有参数的 return 语句返回各个返回变量的当前值。这种用法被称作“裸”返回
    4.多返回值可直接作为其他函数调用实参 
    */

    fmt.Println(addTwo(1,4))
    fmt.Println(addBi(1,4))
    
}

//函数声明:包括函数名、形式参数列表、返回值列表(可省略)以及函数体。
func add(s1 int, s2 int) {
   sum := s1 + s2
   fmt.Println(sum)
}

//引用传参函数;两个变量值掉换
func swap(x, y *int){
    var temp int    
    temp = *x //保存 x 的值 
    *x = *y   //将 y 值赋给 x
    *y = temp //将 temp 值赋给  y
}

/*
任意类型的不定参数:
就是函数的参数和每个参数的类型都不是固定的。
用interface{}传递任意类型数据是Go语言的惯例用法,而且interface{}是类型安全的
*/
func myfunc(args ...interface{}){}
func test(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }
    fmt.Println(s,x)
    return fmt.Sprintf(s, x)
}

//使用 slice 对象做变参时,必须展开
func testSlice(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }
     fmt.Println(s,x)
    return fmt.Sprintf(s, x)
}

//命名返回参数可看做与形参类似的局部变量,最后由 return 隐式返回
func addOne(x, y int)(z int){
    z = x + y
    return
}

//命名返回参数可被同名局部变量遮蔽,此时需要显式返回
func addTwo(x, y int)(z int){
    {
        // 不能在一个级别,引发 "z redeclared in this block" 错误。
        var z = x + y
        // return   // Error: z is shadowed during returnreturn z // 必须显式返回。
        return z
    }
}

//命名返回参数允许 defer 延迟调用通过闭包读取和修改
func addBi(x, y int)(z int){
    defer func(){
        z +=100  //2.再次执行defer行得100+5
        }()
    z = x + y //1.首先执行这行获取数据5
    return
}