Go基础语法(四)

可变参数函数

可变参数函数是一种参数个数可变的函数。

如果函数最后一个参数被记作 ...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

删除 mapkey 的语法是 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~~~

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,033评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,725评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,473评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,846评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,848评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,691评论 1 282
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,053评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,700评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,856评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,676评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,787评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,430评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,034评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,990评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,218评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,174评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,526评论 2 343

推荐阅读更多精彩内容

  • Hello World这是开发的一个开发魔咒,几乎所有人都是从这开始的,今天我也从魔咒开始先打印一份Hello W...
    cocoaAhda阅读 1,429评论 0 3
  • 出处---Go编程语言 欢迎来到 Go 编程语言指南。本指南涵盖了该语言的大部分重要特性 Go 语言的交互式简介,...
    Tuberose阅读 18,398评论 1 46
  • 转载自:https://halfrost.com/go_map_chapter_one/ https://half...
    HuJay阅读 6,120评论 1 5
  • (一) 我叫可乐,可是我一点也不快乐。 在我十三岁那年,我妈因病去世了。从那以后,我再也没看我爸笑过。 他做的饭不...
    可乐要加冰阅读 1,237评论 60 34
  • 那天我平静地给你信息 发自肺腑来自心底 我本是想道别的 因为你已经离开了我 我没有希望没有期待 你会回复你会安慰 ...
    37度女王阅读 162评论 0 0