Golang 常见面试考点汇总及原理解析(2) - map, slice 考点

Slice 切片

slice 的考点一般围绕着 len,cap,append 进行考察,我这里整理了一道面试题,基本覆盖了 slice 中的大多数考点。

题目:下面这段代码的输出结果是什么?

package main
import "fmt"

func sliceAppend(slice []int,v int) []int {
	return append(slice, v)
}

func main() {
	arr := make([]int,5, 10)
	for i := 0;i < 5;i++ {
		arr=append(arr,i)
	}
	
	slice := arr[:]
	slice2 := sliceAppend(slice,1000)
	
	slice3 := arr[:2]
	slice3 = append(slice3, 10)
	
	slice4 := arr[:8]
	sliceAppend(slice4,100)
	
	fmt.Println(arr,len(arr), cap(arr))
	fmt.Println(slice,len(slice), cap(slice))
	fmt.Println(slice2,len(slice2), cap(slice2))
	fmt.Println(slice3,len(slice3), cap(slice3))
	fmt.Println(slice4,len(slice4), cap(slice4))
}

这一题的考点比较多,我们这里总结一下相关的知识,理解了这些知识就能正确解答这道面试题。

  1. slicelencap时是两个完全不同的概念,len代表了元素个数,cap说明slice空间可以容纳多少个元素。
  2. 在对 slice 进行 append 操作时, 如果 cap 容量足够,则直接在当前slice后面附加上添加的值,并将 len 修改为当前元素的个数。
  3. 如果 cap 容量不够,则重新创建一个slice, 并将之前的slice 复制到新的slice中然后将添加的值附加到新的slice上。
  4. slice 出发扩容操作时,如果之前 slicecap小于 2048 时,每次扩容为之前容量的两倍,如果大于 2048 时,则每次增加 512 个 (具体数值和版本有关,大体思路一致)。

正确答案:

[0 0 10 0 100 0 1 2 3 4] 10 10
[0 0 10 0 100 0 1 2 3 4] 10 10
[0 0 0 0 0 0 1 2 3 4 1000] 11 20
[0 0 10] 3 10
[0 0 10 0] 4 10

Map 字典

map 的考点一般围绕着 range 进行考察,下面这两道面试题,基本覆盖了 map 中的大多数考点。

题目1:下面这段代码的输出结果是什么?

package main
import "fmt"
import "strconv"


type Value int
func main() {
	outMap := make(map[string]Value,10)
	for i := 0;i < 10;i++ {
		outMap1[strconv.Itoa(i)] = Value(i)
	}
	
	
	for k,v range outMap {
		fmt.Printf("%v: %v ", k,v)
	}
	fmt.Println()
}

这一题主要考察 map 在使用 range 迭代器对 map 进行遍历时的特性,即:在使用 range 遍历时的顺序时是乱序的,不能确定输出顺序。所以这一题的正确答案是输出结果不能确定。

正确答案:

输出结果不能确定

题目2:下面这段代码的输出结果是什么?

package main
import "fmt"
import "strconv"

func changeMap1(map1 map[string]Value,k string,v Value) {
	map1[k] = v
}
func changeMap2(map2 map[string]*Value,k string,v Value) {
	*map2[k] = v
}

type Value int
func main() {
	outMap1 := make(map[string]Value,10)
	for i := 0;i < 10;i++ {
		outMap1[strconv.Itoa(i)] = Value(i)
	}
	
	outMap2 := make(map[string]*Value,5)
	for k,v := range outMap1 {
		outMap2[k] = &v
	}
	
	outMap1["5"] = 10
	changeMap1(outMap1, "8",100)
	
	*outMap2["2"] = 100
	changeMap2(outMap2, "4",1000)
	
	for i := 0;i < 10;i++ {
		fmt.Printf("%v ", outMap1[strconv.Itoa(i)])
	}
	fmt.Println()
	
	for i := 0;i < 10;i++ {
		fmt.Printf("%v ", *outMap2[strconv.Itoa(i)])
	}
	fmt.Println()
}

这一题看起来代码量挺大,实际上考点还是比较少的,主要还是考察 map 作为参数的传递方式和遍历 map 需要注意的点。

知识点:

  1. map 作为参数传递时是传递的指针,所以修改 map 参数时等于修改原始变量。
  2. 在 使用 range 迭代器对 map 进行遍历时,range 会复制对象,而不是不是直接在原对象上操作。
  3. 在 使用 range 迭代器对 map 进行遍历时,range 会复制对象,并且会重用迭代对象,所以多次遍历的对象实际上是对同一个对象进行重复赋值。

正确答案:

0 1 2 3 4 10 6 7 100 9 
1000 1000 1000 1000 1000 1000 1000 1000 1000 1000 
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值