可变参数函数
可变参数函数是一种参数个数可变的函数。
如果函数最后一个参数被记作 ...T ,这时函数可以接受任意个 T 类型参数作为最后一个参数。
只有函数的最后一个参数才允许是可变的。
package main
import (
"fmt"
)
func find(num int, nums ...int) {
fmt.Printf("type of nums is %T\n", nums)
found := false
for i, v := range nums {
if v == num {
fmt.Println(num, "found at index", i, "in", nums)
found = true
}
}
if !found {
fmt.Println(num, "not found in ", nums)
}
fmt.Printf("\n")
}
func main() {
find(89, 89, 90, 95)
find(87)
}
可变参数函数的工作原理是把可变参数转换为一个新的切片
。
因此以上代码中这三个参数被编译器转换为一个 int 类型切片 int []int{89, 90, 95} 然后被传入 find函数。
在上面代码中,find 函数仅有一个参数时,我们没有给可变参数 nums ...int 传入任何参数。这也是合法的,在这种情况下 nums 是一个长度和容量为 0 的 nil 切片。
给可变参数函数传入切片
直接给可变参数函数传入切片,这种情况下无法通过编译,编译器报出错误 main.go:23: cannot use nums (type []int) as type int in argument to find 。
在上边的代码中可以看到,这些可变参数会被转换为 int 类型切片然后再传入 find 函数中,而如果传入的已经是一个 int 类型切片,
编译器试图在 nums 基础上再创建一个切片,像下面这样:
nums := []int{89, 90, 95}
find(89, []int{nums})
这显然是错误的。
如果非要直接传入切片,有一个可以直接将切片传入可变参数函数的语法糖,你可以在在切片后加上 ... 后缀。如果这样做,切片将直接传入函数,不再创建新的切片。
func main() {
nums := []int{89, 90, 95}
find(89, nums...)
}
易错点1
看下边代码:
package main
import (
"fmt"
)
func change(s ...string) {
s[0] = "Go"
}
func main() {
welcome := []string{"hello", "world"}
change(welcome...)
fmt.Println(welcome)
}
如果使用了 ... ,welcome 切片本身会作为参数直接传入,不需要再创建一个新的切片。这样参数 welcome 将作为参数传入 change 函数
在 change 函数中,切片的第一个元素被替换成 Go,这样程序产生了下面的输出值:
[Go world]
易错点2
继续看代码:
package main
import (
"fmt"
)
func change(s ...string) {
s[0] = "Go"
s = append(s, "playground")
fmt.Println(s)
}
func main() {
welcome := []string{"hello", "world"}
change(welcome...)
fmt.Println(welcome)
}
运行结果:
[Go world playground]
[Go world]
在最初的时候有一句话:GO 语言的参数传递都是 值传递。
这里就是考究的对这句话的理解。 还有就是对slice的理解。
slice 包含 3部分: 长度、容量和指向数组第零个元素的指针 所谓的值传递怎么理解呢,就是传递slice 的时候,把这三个值拷一个副本,传递过去。注意:指针作为值拷贝的副本,指向的是同一个地址,所以修改地址的内容时,原slice也就随之改变。 反之,对拷贝slice副本的修改,如:append,改变的是副本的len、cap,原slice的len、cap并不受影响。
Maps
- map 是在 Go 中将键(key)与值(value)关联的内置类型。通过相应的键可以获取到值。
//创建 map 的语法。
make(map[type of key]type of value)
//创建了一个名为 personSalary 的 map,键是 string 类型,而值是 int 类型。
personSalary := make(map[string]int)
map 的零值是 nil。如果你想添加元素到 nil map 中,会触发运行时 panic。因此 map 必须使用 make 函数初始化。
package main
import (
"fmt"
)
func main() {
var personSalary map[string]int
if personSalary == nil {
fmt.Println("map is nil. Going to make one.")
personSalary = make(map[string]int)
}
}
给map添加元素
这里map添加元素和python中dict很像,直接赋值便可:
func main() {
var personSalary map[string]int
if personSalary == nil {
fmt.Println("map is nil. Going to make one.")
personSalary = make(map[string]int)
}
personSalary["num"] = 2
personSalary["age"] = 24
fmt.Println(personSalary)
}
你也可以在声明的时候初始化 map:
package main
import (
"fmt"
)
func main() {
personSalary := map[string]int{
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
employee := "jamie"
fmt.Println("Salary of", employee, "is", personSalary[employee])
}
如果获取一个不存在的元素,map 会返回该元素类型的零值。
例如:在 personSalary 这个 map 里,如果我们获取一个不存在的元素,会返回 int 类型的零值 0。
map中获取不包含指定key时,不会产生运行错误。
判断map中是否存在指定的key
value, ok := parMap["g"]
如果存在,ok=ture,value=对应的其值
如果不存在,ok=false,value=该map值得类型的零值
func main() {
parMap := map[string]int{
"name":2,
"age":22,
}
fmt.Println(parMap)
value, ok := parMap["g"]
fmt.Println(value, ok)
}
遍历map
使用for := range遍历
for value, key := range parMap
package main
import (
"fmt"
)
func main() {
personSalary := map[string]int{
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
fmt.Println("All items of a map")
for key, value := range personSalary {
fmt.Printf("personSalary[%s] = %d\n", key, value)
}
}
有一点很重要,当使用 for range 遍历 map 时,不保证每次执行程序获取的元素顺序相同。
删除map中的key
删除 map
中 key
的语法是 delete(map, key)。这个函数没有返回值。
package main
import (
"fmt"
)
func main() {
personSalary := map[string]int{
"steve": 12000,
"jamie": 15000,
}
personSalary["mike"] = 9000
fmt.Println("map before deletion", personSalary)
delete(personSalary, "steve")
fmt.Println("map after deletion", personSalary)
}
获取map的长度
使用len()函数获取map的长度
len(personSalary)
注意:
Map是引用类型,和 slices 类似。当 map 被赋值为一个新变量的时候,它们指向同一个内部数据结构。因此,改变其中一个变量,就会影响到另一变量。
当 map 作为函数参数传递时也会发生同样的情况。函数中对 map 的任何修改,对于外部的调用都是可见的。
map 之间不能使用 == 操作符判断,== 只能用来检查 map 是否为 nil。会报错: invalid operation: map1 == map2 (map can only be compared to nil)。
如果文章对您有帮助,记得点个赞,后续持续更新ing~~~