当前位置:网站首页>一道golang中关于for range常见坑的面试题

一道golang中关于for range常见坑的面试题

2022-07-23 20:41:00 youngqqcn

以下代码运行,会输出什么?

package main

import "fmt"

type student struct {
    
	Name string
	Age  int
}

func pase_student() {
    
	m := make(map[string]*student)
	stus := []student{
    
		{
    Name: "A", Age: 1},
		{
    Name: "B", Age: 2},
		{
    Name: "C", Age: 3},
	}
	for _, stu := range stus {
    
		m[stu.Name] = &stu
	}

	for k, v := range m {
    
		fmt.Printf("%v,%v,%v\n", k, v.Name, v.Age)
	}
}


func main() {
    
	pase_student()
}

请思考,答案在文末
























答案

A,C,3
B,C,3
C,C,3

为什么?

因为在golangfor range中,临时变量stu会被复用,然后将新的值复制进去,而不会另开辟空间。所以题目中m[stu.Name] = &stu,会导致stu中的值会是最后一次复制进去的值,即stus最后一个值。

我们可以写个测试程序,验证这个“坑”:

func main() {
    

	a := []int{
    1, 2, 3, 4}

	for x, n := range a {
    
		fmt.Printf("%d: %d\n", x, n)
		fmt.Printf("%p\n", &n)
	}
}

输出

0: 1
0xc0000160c8
1: 2
0xc0000160c8
2: 3
0xc0000160c8
3: 4
0xc0000160c8

可以看到,每次&n都是固定的

如何修改?

第1种,使用值,而不是指针。可以将 m := make(map[string]*student) 改成 m := make(map[string]student) , 完整代码如下:


func pase_student() {
    
	m := make(map[string]student)
	stus := []student{
    
		{
    Name: "A", Age: 1},
		{
    Name: "B", Age: 2},
		{
    Name: "C", Age: 3},
	}
	for _, stu := range stus {
    
		m[stu.Name] = stu
	}

	for k, v := range m {
    
		fmt.Printf("%v,%v,%v\n", k, v.Name, v.Age)
	}
}

第2种,不用for range改用经典的for

func pase_student() {
    
	m := make(map[string]student)
	stus := []student{
    
		{
    Name: "A", Age: 1},
		{
    Name: "B", Age: 2},
		{
    Name: "C", Age: 3},
	}
	for i := 0; i < len(stus); i++ {
    
		m[stus[i].Name] = stus[i]
	}

	for k, v := range m {
    
		fmt.Printf("%v,%v,%v\n", k, v.Name, v.Age)
	}
}

其他方式也可以。

所以,在实际项目开发中,用到for range时赋值时一定要注意这个“坑”

原网站

版权声明
本文为[youngqqcn]所创,转载请带上原文链接,感谢
https://blog.csdn.net/yqq1997/article/details/125950309