作者:ReganYue
起源:恒生LIGHT云社区
Go语言学习查缺补漏ing Day5
一、将切片当可变参数传递的一个问题
咱们来看一段代码:
package mainimport "fmt"func Myfunc(num ...int) { num[0] = 2 total := 0 for _, i := range num { total += i } num[1] = total}func Sum(num ...int) { total := 0 for _, i := range num { total += i } num[1] = total}func main() { i := []int{1, 2, 3} Myfunc(i...) fmt.Println(i) Sum(i...) fmt.Println(i)}
这段代码的运行后果是:
[2 7 3][2 12 3]
是不是很奇怪为什么切片内的值扭转了?其实咱们将切片作为函数参数传递给函数是进行的值传递,所以咱们传递给函数的参数其实是上面这个slice的值拷贝。
type slice struct{ value *int length uint capacity uint }
然而,这个slice构造体内的value是一个指针,所以这个slice就算进行了拷贝,它和它的拷贝值都是同一个value,指向同一块区域。
所以下面的代码,咱们能够在Myfunc和Sum函数中对main函数内的i切片进行操作。
然而,当咱们对num切片进行扩容操作时,拷贝值的value指向的地址就可能会发生变化。
比方咱们进行上面的操作:
func Sum(num ...int) { num[0] = 8 total := 0 for _, i := range num { total += i } num = append(num, total) num[1] = total}
运行后果是:
[2 7 3][8 7 3]
这就侧面形容了slice的扩容算法。
另外说到可变参数,咱们还须要留神几点,这里咱们应该理解可变长参数应该是函数头中最初一个参数!!!
有些人会纳闷,不是说可变参数吗?怎么传入了一个切片?其实可变参数的底层就是用切片实现的,它是将传入的一个或多个参数转换为一个切片。
二、Go中不容许不同类型的数据进行运算
咱们都晓得,Go中具备极其严格的动态类型限度,只有雷同类型的数据能力进行运算,那么如何解决这个问题呢?
第一点天然是强制类型转换。比方:
func main() { var ( i int = 3 j float32 = 3.1 ) fmt.Println(float32(i) + j)}
这个程序运行就不会编译谬误,运行后果是6.1。
还有一种办法,不过实用场景比拟繁多。就是定义无类型常量。比方:
package mainimport ( "fmt")func main() { const i = 1 const j = 2.1 fmt.Println(i + j)}
运行就不会报错,运行后果是3.1.
三、不同长度数组是否进行比拟
看一看上面这段代码:
package mainimport ( "fmt")func main() { a := [2]int{1, 2} b := [3]int{1, 2} if a == b { fmt.Println("equal") } else { fmt.Println("not equal") }}
你感觉他们相不相等?
哈哈哈哈
其实都不能通过编译,因为数组的长度是数组的一部分,所以两个数组不是雷同的类型,所以他们无奈进行比拟,故会报错:
invalid operation: a == b (mismatched types [2]int and [3]int)
四、对于map的一点须要留神的中央
咱们先来看看这段代码:
package mainimport ( "fmt")func main() { Map := make(map[string]int) delete(Map, "map") fmt.Println(Map["map"])}
Map是空的,你感觉会报错吗?如果不报错,会输入什么?
答案是不会报错,会输入0.
是不是想对了?上面来解释一下:
Go设计的就是删除map中不存在的键值对时不会报错,另外获取map中并不存在的键值对时,获取到的是值类型的零值。