介绍Go中将切片当可变参数传递的一个问题等四个问题

举报
Regan Yue 发表于 2021/11/23 15:31:17 2021/11/23
【摘要】 Go语言学习查缺补漏ing Day5一、将切片当可变参数传递的一个问题我们来看一段代码:package main​import "fmt"​func Myfunc(num ...int) { num[0] = 2 total := 0 for _, i := range num { total += i } num[1] = total}func ...

Go语言学习查缺补漏ing Day5

一、将切片当可变参数传递的一个问题

我们来看一段代码:

package main
​
import "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 main
​
import (
    "fmt"
)
​
func main() {
    const i = 1
    const j = 2.1
​
    fmt.Println(i + j)
}
​

运行就不会报错,运行结果是3.1.

三、不同长度数组能否进行比较

看一看下面这段代码:

package main
​
import (
    "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 main
​
import (
    "fmt"
)
​
func main() {
    Map := make(map[string]int)
    delete(Map, "map")
    fmt.Println(Map["map"])
}

Map是空的,你觉得会报错吗?如果不报错,会输出什么?

答案是不会报错,会输出0.

是不是想对了?下面来解释一下:

Go设计的就是删除map中不存在的键值对时不会报错,另外获取map中并不存在的键值对时,获取到的是值类型的零值。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。