go新手常踩的坑

作为一个5年的phper,这两年公司和个人都在顺应技术趋势,新项目慢慢从php转向了go语言,从2021年到现在,笔者手上也先后开发了两个go项目。在学习go语言的过程中也学习并总结了一些相关的东西,这篇文章就分享下自己踩过的一些坑吧。

1、函数的写法

问题:

func main()
{
	fmt.Println("php是世界上最好的语言")
}

解决:
如上所示,这种函数的定义写法,在go语言中是错误的,就是 "{" 必须得和函数名在同一行。当然,这种错误在编辑器检测语法的时候就会暴露出来了,正确写法应该如下所示:

func main() {
	fmt.Println("php是世界上最好的语言")
}

2、map定义和初始化

问题:

func main() {
	var m map[string]string
	m["php"] = "世界上最好的语言"
	m["go"]  = "世界上最好的语言"
	fmt.Println(m)
}

解决:
如上所示,这种定义了map,然后直接使用的方式是错误的,会抛出一个panic。少了一个重要的步骤,必须使用make()函数去给map分配内存空间,才能使用。这个对于phper来说,刚开始可能会经常忘掉。正确使用方式如下:

func main() {
	m := make(map[string]string, 2)
	m["php"] = "世界上最好的语言"
	m["go"]  = "世界上最好的语言"
	fmt.Println(m)
}

3、json格式转换

问题:

type Student struct {
	id    int
	name  string
	score int
}

func main() {
	s := Student{1, "小明", 99}
	jsonS, _ := json.Marshal(s)
	fmt.Println(string(jsonS))
}

解决:
在做web开发过程中,基本上每天都要和json格式数据打交道,所以学会转换成json格式的数据是必备技能啊。但上面的写法是错误的,打印出来的为空值。这是因为Student结构体中的元素都是小写的,对外是不可访问的,所以必须改成大写的,才能对外输出json格式的数据。正确写法如下:

type Student struct {
	Id    int
	Name  string
	Score int
}

func main() {
	s := Student{1, "小明", 99}
	jsonS, _ := json.Marshal(s)
	fmt.Println(string(jsonS))
}

4、循环中处理业务问题

问题:

func main() {
	data := []int{1, 2, 3}
	for _, value := range data {
		value += 1
	}
	fmt.Println(data)
}

解决:
如上所示,我们本身是想对data里面的元素做加1操作的,但发现没有成功。那是因为,我们循环所引用的变量是临时变量,去修改的时候并不会改变数组中的原有结构。正确的做法应该是根据切片的索引去修改,其实就类似于php的foreach,改变数组中的值,也是需要根据索引去改的。如下所示:

func main() {
	data := []int{1, 2, 3}
	for key := range data {
		data[key] += 1
	}
	fmt.Println(data)
}

5、数组和切片的区别

问题:

func change(data [2]int) {
	data[0] = 4
}

func main() {
	data := [2]int{1, 2}
	change(data)
	fmt.Println(data)
}

解决:
如上所示,运行的结果是[1 2] ,而不是[4 2] 。原因是main方法中声明的data是数组,而go语言中的参数传递是值传递,所以不会改变原有的数组值。如果需要实现上述效果,可以改用切片,因为切片本身不会存储数据,他的底层数据会指向一个底层数组,因此在修改切片的元素时,会修改底层数组的相应元素,同时共享同一个底层数组的切片也会相应修改。正确做法如下所示:

func change(data []int) {
	data[0] = 4
}

func main() {
	data := []int{1, 2}
	change(data)
	fmt.Println(data)
}

6、:= 声明和初始化变量

问题:

func main() {
	flag := 1
	if true {
		flag := 2
		flag++
	}
	fmt.Println(flag)
}

解决:
如上所示,运行结果仍然是1,而不是2或者3。上述代码中,flag := 2,又重新声明了一个变量flag,但它作用的仅仅是if 判断逻辑里面的,并没有作用到整个main函数全局中。如果要正确影响,应将 := 改为 =,如下所示,结果则为3:

func main() {
	flag := 1
	if true {
		flag = 2
		flag++
	}
	fmt.Println(flag)
}

总结:以上,就是本人在实际开发中,结合自己所学,遇到的一些比较常见的坑点了。当然,也是比较基础的一些点。后面,我也会继续深入学习go,总结更多的经验!

posted @ 2022-06-07 15:36  snail_lmz  阅读(36)  评论(0编辑  收藏  举报