go函数参数总结

学编程语言是要解决实际问题,只作“语言律师”肯定不好,只有作品才是最好的证明。

尽管如此,了解语言的基础细节可以避免我们在工作中分心,使我们专注于手头工作,免受语法或某些副作用的干扰,从这个意义上讲,了解细节是有实际意义的。

本文说明以下几个问题

一: 形参 是 实参 一个别名,形参本身也是一个变量,形参本身也有自己的地址。

二:array, struct, string, int 都不是指针变量。

三:slice指针变量 拥有的值 是 底层数组某个元素的地址。

四:只有 slice, map 才是指针变量。

以下是实际代码展示

一: 形参 是 实参 一个别名,形参本身也是一个变量,形参本身也有自己的地址。

func TestFormalParam(t *testing.T) {
	slc := []string{"a0", "a1", "a2", "a3", "a4"}
	fmt.Printf("slc=%p, &slc=%p, slc=%v\n", slc, &slc, slc)
	setValue(slc)
	fmt.Printf("slc=%p, &slc=%p, slc=%v\n", slc, &slc, slc)
}

func setValue(slc2 []string) {
	fmt.Printf("slc2=%p, &slc2=%p, slc2=%v\n", slc2, &slc2, slc2)
	slc2[0] = "诸葛村夫"
	slc2[1] = "织席贩履"
	slc2[2] = "大耳刘贼"
}

a. 实参slc 本身的地址(0xc000004520) 和 形参 slc2本身的地址(0xc000004580) 当然各不相同。

b. 实参slc 和 形参slc2 这俩指针变量 拥有值一样,即,这俩 指针变量 都指向同一 内存地址 0xc0000480f0。

二:array, struct, string, int 都不是指针变量。

func TestArray(t *testing.T) {
	arr := [5]string{"a0", "a1", "a2", "a3", "a4"}
	fmt.Printf("arr=%p, &arr=%p\n", arr, &arr)
}

a. array, struct, string, int 都是无法 %p 打印地址,编译就会报错。

b. slice, map 可以 %p 打印地址。slice变量,map变量 其实就是一根指针。

三:slice指针变量 拥有的值 是 底层数组某个元素的地址。

func TestArrayAndSlice(t *testing.T) {
	arr := [5]string{"a0", "a1", "a2", "a3", "a4"}
	for idx, _ := range arr {
		fmt.Printf("arr[%d]=%v, &arr[%d]=%p\n", idx, arr[idx], idx, &(arr[idx]))
	}
	fmt.Println()

	slc0 := arr[0:]
	fmt.Printf("slc0=%p, &slc0=%p\n", slc0, &slc0)

	slc2 := arr[2:]
	fmt.Printf("slc2=%p, &slc2=%p\n", slc2, &slc2)
}

a. slc0指针变量 拥有的值 就是 元素 arr[0]的地址。

b. slc2指针变量 拥有的值 就是 元素 arr[2]的地址。

c. 当然,指针变量本身 当然也存在地址,即:&slc0,&slc2。

四:只有 slice, map 才是指针变量。

type ComplexStruct struct {
	str  string
	num  int32
	arr  [2]string
	slc  []string
	slcC []string
	m    map[string]int32
}

func TestStruct(t *testing.T) {
	cs := ComplexStruct{
		str:  "Hello",
		num:  911,
		arr:  [2]string{"ChinaSystem", "ZTE"},
		slc:  []string{"January", "February"},
		slcC: []string{"Monday", "Tuesday"},
		m:    map[string]int32{"pow": 2, "sin": 1},
	}
	fmt.Printf("1--\ncs=%p\n%v\ncs.slcC=%p, &cs.slcC=%p\n\n", &cs, cs, cs.slcC, &cs.slcC)
	changeCS(cs)
	//入参非指针时,slc, map都会改变,其他都不会
	fmt.Printf("4--\ncs=%p\n%v\ncs.slcC=%p, &cs.slcC=%p\n\n", &cs, cs, cs.slcC, &cs.slcC)
}

func changeCS(cs ComplexStruct) {
	fmt.Printf("2--\ncs=%p\n%v\ncs.slcC=%p, &cs.slcC=%p\n\n", &cs, cs, cs.slcC, &cs.slcC)
	cs.str = "蓝色星球"
	cs.num = 9527
	cs.arr[0] = "比亚迪"
	cs.slc[0] = "十二月过年了"
	cs.slcC[0] = "星期一"
	cs.slcC = append(cs.slcC, "星期三")
	cs.slcC = append(cs.slcC, "星期四")
	cs.slcC = append(cs.slcC, "星期五")
	cs.slcC = append(cs.slcC, "星期六")
	cs.m["a平方根"] = 38
	fmt.Printf("3--\ncs=%p\n%v\ncs.slcC=%p, &cs.slcC=%p\n\n", &cs, cs, cs.slcC, &cs.slcC)
}

 A:1,2,3,4 说明:slice就是一个指针变量(再次强调)。参数传递struct时,位于struct内的

slice当然也是指针变量。

B:1,2,5,6说明:“形参是实参的别名”,这两个 指针变量 本身的地址 &cs.slcC 不同;但这两个指针变量拥有同样的值,即指向同一个内存地址 0xc00008e4e0。

C:7说明:string, int, array 都不是 指针变量(注意:array 也不是指针变量哦),所以,在另一个函数中修改后,不影响原来的值。

D:8说明:给slice append值时,由于slice扩大

    a. “形参是实参的别名”。修改cs.slcC[0]时,主调函数中的 和被调函数中的 cs.slcC 指针变量 此时还拥有同样的值,所以,修改被调函数中cs.slcC[0],主调函数中也可以看到。

    b. 在被调函数中,由于slice扩大,cs.slcC指针变量 指向的地址 从原来的地址(0xc00008e4e0)换到一个新的地址(0xc0000e6080)。

    c. 主调函数中cs.slcC指针变量 指向的地址 没有任何变化(0xc00008e4e0),回到主调函数时,只能看到a处所做的修改。

完!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Golang 中,可以使用内置的 `testing` 包来编写单元测试代码。以下是编写测试函数的步骤: 1. 在需要测试的文件中,创建一个名为 `xxx_test.go` 的文件,其中 `xxx` 表示需要测试的文件名。 2. 在该文件中定义名为 `TestXxx` 的测试函数,其中 `Xxx` 表示需要测试的函数名。 3. 在 `TestXxx` 函数中编写测试代码,使用内置的 `testing` 包中的函数来进行测试断言。 4. 在命令行中使用 `go test` 命令来运行测试代码,并查看测试结果。 下面是一个示例: 假设我们有一个名为 `stringutil` 的 package 包,其中包含了一个名为 `ToUpper` 的函数,用于将字符串转换为大写。我们可以编写一个名为 `stringutil_test.go` 的文件,用于测试该函数的正确性。 ```go package stringutil import "testing" func TestToUpper(t *testing.T) { s := "hello, world!" expected := "HELLO, WORLD!" result := ToUpper(s) if result != expected { t.Errorf("ToUpper(%s) = %s; expected %s", s, result, expected) } } ``` 在上面的示例中,我们定义了一个名为 `TestToUpper` 的测试函数,用于测试 `ToUpper` 函数的正确性。我们使用内置的 `testing` 包中的函数 `t.Errorf` 来进行测试断言,如果测试失败,会输出错误信息。 需要注意的是,测试函数的命名必须以 `Test` 开头,并且参数列表中必须包含一个名为 `*testing.T` 的参数,用于输出测试结果。 在命令行中运行 `go test` 命令,将会自动运行所有的测试函数,并输出测试结果。 总结: 通过编写测试函数,可以确保代码的正确性,避免出现潜在的问题。在实际的开发过程中,建议编写完整的测试代码,以确保代码的稳定性和可靠性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值