/ 2018-12-10
函数参数
实际参数简称“实参”。在调用有参函数时,函数名后面括号中的参数称为“实际参数”,实参可以是常量、变量或表达式。
自定义函数中的“形参”全称为"形式参数" 由于它不是实际存在变量,所以又称虚拟变量。实参和形参可以重名。形参的作用域是整个函数体就像定义在函数体内的局部变量。
参数传递
第一种,值传递:指在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。
package main import ( "fmt" ) func main() { var x int = 1 var y int = 2 // 值传递 z := sum(x, y) fmt.Println(z) } func sum(x, y int) int { return x + y }
第二种,引用传递:是指在调用函数时将实际参数的地址传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
package main import ( "fmt" ) func swap(x, y *string) { var temp string temp = *x *x = *y *y = temp } func main() { var course1, course2 string = "Python", "Golang" swap(&course1, &course2) fmt.Println(course1, course2) }
第三种,固定类型可变参数:就是函数的参数不是固定的,后面的类型是固定的。
package main import ( "fmt" ) func variable(name string, course ...string) { fmt.Println("可变参数的长度:", len(course)) for _, val := range course { fmt.Println(name, val) } } func main() { variable("oldboy", "linux", "golang", "python", "java") }
第四种,任意类型的不定参数:就是函数的参数和每个参数的类型都不是固定的。形参用interface{}传递任意类型数据。
package main import ( "fmt" ) type Person struct { name string } func variable(values ...interface{}) { for _, val := range values { switch v := val.(type) { case int: fmt.Println("val type is int ", v) case float64: fmt.Println("val type is float ", v) case string: fmt.Println("val type is string ", v) case bool: fmt.Println("val type is bool ", v) case Person: fmt.Println("val type is Person ", v.name) case *Person: fmt.Println("val type is *Person ", v.name) default: fmt.Println("val type is unknow ", v) } } } func main() { temp_int := 1 temp_float := 5.6 temp_string := "hello" temp_bool := true temp_person1 := &Person{name: "jack"} temp_person2 := Person{name: "rose"} var temp_float32 float32 = 6.6 variable(temp_int, temp_float, temp_string, temp_bool, temp_person1, temp_person2, temp_float32) }
第五种,函数类型参数:就是函数类型赋值给变量,作为参数传递应用。
package main import "fmt" // 定义函数类型 type myfunc func(string, string) func addperfix(perfix, name string) { fmt.Println(perfix, name) } // 第二个参数用匿名函数当参数 func sayhello(name string, f myfunc) { f("hello", name) } func main() { sayhello("oldboy", addperfix) }
注意:
1)Go语言函数中的参数不支持默认值。
2)无论是值传递,还是引用传递,传递给函数的都是变量的副本,不过,值传递是值的拷贝。引用传递是地址的拷贝,一般来说,地址拷贝更为高效。而值拷贝取决于拷贝的对象大小,对象越大,则性能越低。
3)map、slice、chan、指针、interface默认以引用的方式传递。
4)函数的可变参数只能有一个,且必须是最后一个。
5)在参数赋值时可以不用用一个一个的赋值,可以直接传递一个数组或者切片,特别注意的是在参数后加上“…”即可。实例如下:
package main import ( "fmt" ) func oldboy(name string, c ...string) string { var course string for _, val := range c { course += val } return fmt.Sprintf(name, course) } func main() { course := []string{"linux ", "golang ", "python ", "java"} res := oldboy("oldboy: %s", course...) // ... 展开slice fmt.Println(res) }
(8)