1.下面代码输出什么,为什么
//make([]T, length, capacity)
s1 := []int{
1, 2, 3}
fmt.Println(s1, "哈哈") //[1 2 3]
s2 := s1
fmt.Println(s1, "哈哈") //[1 2 3]
for i := 0; i < 3; i++ {
s2[i] = s2[i] + 1
}
fmt.Println(s1) //[2 3 4]
fmt.Println(s2) //[2 3 4]
[1 2 3] 哈哈
[1 2 3] 哈哈
[2 3 4]
[2 3 4]
注:引用就是同一份,相当于起了一个别名,就是多起了一个名字而已。
在Go语言中的引用类型有:映射(map),数组切片(slice),通道(channel),方法与函数。
整型,字符串,布尔,数组在当作参数传递时,是传递副本的内存地址,也就是值传递。
2.下面代码输出什么,为什么
func rmLast(a []int) {
fmt.Println("a", a)
a = a[:len(a)-1]
for i := 0; i < 13; i++ {
a = append(a, 8)
}
fmt.Println("rm后a", a)
// fmt.Println(len(a))
}
func updateLast(a []int) {
fmt.Println("a", a)
for i := 0; i < len(a); i++ {
a[i] = a[i] + 1
}
fmt.Println("修改后a", a)
// fmt.Println(len(a))
}
func main() {
xyz := []int{
1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println("xyz", xyz)
rmLast(xyz)
fmt.Println("rm后xyz", xyz)
updateLast(xyz)
fmt.Println("修改后xyz", xyz) //[1 2 3 4 5 6 7 8 9]
}
xyz [1 2 3 4 5 6 7 8 9]
a [1 2 3 4 5 6 7 8 9]
rm后a [1 2 3 4 5 6 7 8 8 8 8 8 8 8 8 8 8 8 8 8 8]
rm后xyz [1 2 3 4 5 6 7 8 8]
a [1 2 3 4 5 6 7 8 8]
修改后a [2 3 4 5 6 7 8 9 9]
修改后xyz [2 3 4 5 6 7 8 9 9]
注:函数内改切片的值,外部是可见的,改切片的长度外部是不可见的
3.下面代码输出什么,为什么
//n1是n2的底层数组
n1 := [3]int{
1, 2, 3}
n2 := n1[0:3]
fmt.Println("下面是n1地址 ")
for i := 0; i < len(n1); i++ {
fmt.Printf("%p\n", &n1[i])
}
fmt.Println(n1)
fmt.Println("下面是n2地址 ")
for i := 0; i < len(n2); i++ {
fmt.Printf("%p\n", &n2[i])
}
fmt.Println(n2)
n2 = append(n2, 1)
fmt.Println("下面是n1地址 ")
for i := 0; i < len(n1); i++ {
fmt.Printf("%p\n", &n1[i])
}
fmt.Println(n1)
fmt.Println("下面是n2地址 ")
for i := 0; i < len(n2); i++ {
fmt.Printf("%p\n", &n2[i])
}
fmt.Println(n2)
下面是n1地址
0xc000064140
0xc000064148
0xc000064150
[1 2 3]
下面是n2地址
0xc000064140
0xc000064148
0xc000064150
[1 2 3]
下面是n1地址
0xc000064140
0xc000064148
0xc000064150
[1 2 3]
下面是n2地址
0xc000090030
0xc000090038
0xc000090040
0xc000090048
[1 2 3 1]
4.下面代码输出什么,为什么
func defer_call(y int) {
for i := 0; i < 5; i++ {
defer fmt.Println("输出y+i", y+i)
fmt.Println("哈哈")
defer fmt.Println("输出i ", i)
}
}
func main() {
defer_call(5)
}
哈哈
哈哈
哈哈
哈哈
哈哈
输出i 4
输出y+1 9
输出i 3
输出y+1 8
输出i 2
输出y+1 7
输出i 1
输出y+1 6
输出i 0
输出y+1 5
注:先执行"哈哈",
退出defer_call这个函数时,反序执行以下函数
fmt.Println("输出y+i",5)
fmt.Println("i",0)
fmt.Println("输出y+i",6)
fmt.Println(....)
fmt.Println("输出y+i",9)
fmt.Println("i",4)
5.下面代码输出什么
func main() {
for i := 0; i < 5; i++ {
fmt.Println(i, "haha")
//匿名函数:匿名函数可以在声明后调用
go func() {
time.Sleep(3 * time.Second)
fmt.Println(i, "嗯嗯")
}()
}
time.Sleep(10 * time.Second)
}
0 haha
1 haha
2 haha
3 haha
4 haha
5 嗯嗯
5 嗯嗯
5 嗯嗯
5 嗯嗯
5 嗯嗯
6.下面代码输出什么
func main() {
strs := []string{
"one", "two", "three"}
for _, s := range strs {
//1.主线程都快结束了(主线程跑到three了),并发出来的线程才刚开始
//2.这里匿名函数不传参的话,是共享的s的地址,所以打印出来的都是three
go func() {
time.Sleep(1 * time.Second)
fmt.Printf("%s ", s)
}()
}
time.Sleep(3 * time.Second)
}
three three three
7.下面代码输出什么
func main() {
strs := []string{
"one", "two", "three"}
for _, s := range strs {
go func(s string) {
time.Sleep(1 * time.Second)
fmt.Printf("%s ", s)
}(s)
}
time.Sleep(3 * time.Second)
}
three one two
one two three
one three two
注:并发出来三个线程,哪个先结束不一定,所以输出不固定
8.下面代码输出什么
func main() {
x := []string{
"ha", "b", "c"}
for v := range x {
fmt.Print(v)
}
}