一、Function
Go 语言中,函数的参数,无论是基本类型、结构体、指针,都会对传递的参数进行拷贝。
但呈现方式并不都是值传递,原因是指针类型作为参数传递时,函数内部会对指针进行复制,会同事出现俩个指针指向原有的内存地址,所以 Go 语言中,传指针 == 传值
- 传值:函数调用时会对参数进行拷贝,被调用方和调用方两者持有不相关的两份数据;
- 传引用:函数调用时会传递参数的指针,被调用方和调用方两者持有相同的数据,任意一方做出的修改都会影响另一方。
1-1 func 参数传递方式 - 值传递和引用传递类型总结
注意:函数的传参方式都是传值拷贝,但是若参数为引用类型,则会修改原地址内容!
值传递类型:int、string、struct、array
引用传递类型:指针、map、slice、channel
package main
import "fmt"
func main() {
int_data := 3
string_data := "str"
array_data := [3]int{
1, 2, 3}
slice_data := []int{
1, 2, 3}
info := map[string]int{
"1": 2,
"3": 4,
"5": 6,
}
func(int_data int) {
int_data *= 10
}(int_data)
func(string_data string) {
string_data = string_data + "hello"
}(string_data)
func(array_data [3]int) {
array_data[0] = 888
}(array_data)
func(slice_data []int) {
slice_data[0] = 999
}(slice_data)
func(info map[string]int) {
info["1"] = 777
}(info)
fmt.Println("int_data:", int_data) // prints int_data: 3
fmt.Println("string_data:", string_data) // prints string_data: str
fmt.Println("array_data:", array_data) // prints array_data: [1 2 3]
fmt.Println("slice_data:", slice_data) // prints slice_data: [999 2 3]
fmt.Println("info:", info) // prints info: map[1:777 3:4 5:6]
}
1-2 简式声明仅仅可在函数内部使用且不可重复
package main
myvar := 1 // error - 全局的简式声明
var myvar = 1 // works
func main() {
one := 0
one := 1 //error 单个声明中不可重复声明同一个变量
// 但在多变量声明中,可以重复变量名,但其中至少要有一个新的变量声明
one, two := 1,2
one,two = two,one
}
// 重复变量需要在相同的代码块内,否则你将得到一个隐藏变量。
1-3 普通函数 vs 绑定方法
1-3-1 指针形参的实参接受
package main
import "fmt"
type Vertex struct {
X, Y float64
}
// 绑定 Vertex 的方法 Scale,指针形参
// 实参可谓指针 or 地址
func (v *Vertex) Scale(f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
// 普通方法,指针形参
// 实参只能是指针
func ScaleFunc(v *Vertex, f float64) {
v.X = v.X * f
v.Y = v.Y * f
}
func main() {
v := Vertex{
3, 4}
v.Scale(2)
fmt.Println(v) // {6 8}
// Go 会将语句 v.Scale(5) 解释为 (&v).Scale(5)。
ScaleFunc(&v, 10)
// ScaleFunc(v, 10) error
fmt.Println(v) // {60 80}
p := &Vertex{
4, 3}
p.Scale(3)
fmt.Println(p) // &{12 9}
ScaleFunc(p, 8)
fmt.Println(p) // &{96 72}
fmt.Println