关于golang中平行赋值浅析

对于golang, 交换两个数很简单,如下这么写就可以了:

i, j = j, i

等号左边和右边含有多个表达式,这就是平行赋值。 赋值分为两个步骤:

  • 计算等号左边的操作数的索引表达式和取址表达式,计算等号右边的表达式。
  • 赋值

我们来看下面一段代码会输出什么?

func main() {
 i := 1
 s := []string{"A", "B", "C"}
 i, s[i-1] = 2, "Z"
 fmt.Printf("s: %v \n", s)
}

这里输出的 s: [Z,B,C] 而不是s: [A,Z,C]。 这是因为等号左边的切片的索引表达式i-1会被先计算,最后才是赋值。 计算和赋值的顺序,都是从左往右。 我们再来看下面的代码会输出什么?

func main() {
 a := []int{1, 2, 3, 4}
 defer func(a []int) {
  fmt.Printf("a: %v\n", a)
 }(a)
 a[0], a[4] = a[1], a[2]
}

输出的是:

a: [2 2 3 4]
panic: runtime error: index out of range

goroutine 1 [running]:

在赋值的过程中,即使后面的引发了panic,前面的也会被赋值成功。 再看这个会输出什么?

func main() {
 a := []int{1, 2, 3, 4}
 defer func(a []int) {
  fmt.Printf("a: %v\n", a)
 }(a)
 a[0], a[1] = a[2], a[4]
}

输出的是:

a: [1 2 3 4]
panic: runtime error: index out of range

goroutine 1 [running]:
main.main()

再次理解一下,赋值的第一步,计算等号左边的索引表达式,取址表达式 和 计算等号右边的表达式。

理解参照了《Go并发编程一书》

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • Go语言实现字符串切片赋值的方法小结

    前言 在所有编程语言中都涉及到大量的字符串操作,可见熟悉对字符串的操作是何等重要.本文通过示例详细介绍了Go语言实现字符串切片赋值的方法,感兴趣的朋友们跟着小编一起来看看吧. 1. 在for循环的range中 func StrRangeTest() { str := []string{"str1", "str2", "str3"} for i, v := range str { fmt.Println(i, v) v = "test&q

  • Go语言中的变量声明和赋值

    1.变量声明和赋值语法 Go语言中的变量声明使用关键字var,例如 复制代码 代码如下: var name string //声明变量 name = "tom" //给变量赋值 这边var是定义变量的关键字,name是变量名称,string是变量类型,=是赋值符号,tom是值.上面的程序分两步,第一步声明变量,第二步给变量赋值.也可以将两步合到一起. 复制代码 代码如下: var name string = "tom" 如果在声明时同时赋值,可以省略变量类型,Go语

  • go和python变量赋值遇到的一个问题

    平时写得多的是python,最近看了一点go,今天碰到了一个问题,和大家分享一下 package main import "fmt" type student struct { Name string Age int } func pase_student() { m := make(map[string]*student) stus := []student{ {Name: "zhou", Age: 24}, {Name: "li", Age:

  • 关于golang中平行赋值浅析

    对于golang, 交换两个数很简单,如下这么写就可以了: i, j = j, i 等号左边和右边含有多个表达式,这就是平行赋值. 赋值分为两个步骤: 计算等号左边的操作数的索引表达式和取址表达式,计算等号右边的表达式. 赋值 我们来看下面一段代码会输出什么? func main() { i := 1 s := []string{"A", "B", "C"} i, s[i-1] = 2, "Z" fmt.Printf(&quo

  • 浅析Golang中的内存逃逸

    目录 什么是内存逃逸分析 为什么需要逃逸分析 如果变量放错了位置会怎样 内存逃逸场景 return 局部变量的指针 interface{} 动态类型 栈空间不足 闭包 性能 最后 什么是内存逃逸分析 内存逃逸分析是go的编译器在编译期间,根据变量的类型和作用域,确定变量是堆上还是栈上 简单说就是编译器在编译期间,对代码进行分析,确定变量分配内存的位置.如果变量需要分配在堆上,则称作内存逃逸了. 为什么需要逃逸分析 因为go语言是自动自动内存管理的,也就是有GC的.开发者在写代码的时候不需要关心考

  • 浅析Golang中字符串拼接问题

    目录 1.概述 2.Golang中字符串拼接的方式 3.总结 1.概述 Go的字符串是一个不可改变的数据结构,这和其他语言如JAVA,C++等的设定很类似.总体来说,有如下五种拼接方式,下面我们将论述各种方式的性能问题,以及如何选择. (golang字符串,内存模型) type StringHeader struct { Data uintptr Len int } 注意:字符串具有不可改变的特性,即便通过指针等变相操作 var a string = "old" bptr := (*r

  • 浅析Python中的赋值和深浅拷贝

    python中,A object  = B object  是一种赋值操作,赋的值不是一个对象在内存中的空间,而只是这个对象在内存中的位置 . 此时当B对象里面的内容发生更改的时候,A对象也自然而然的会跟着更改. name = ["root","admin"] cp_name = name # 对cp_name进行赋值操作 # 对name列表进行插入 name.append('root_temp') print(name,cp_name) # ['root', 'a

  • Golang map实现原理浅析

    目录 map的声明 map声明 map使用的方式 map遍历 map切片 map 排序 map使用细节 map的练习题 map的声明 基本语法 var map变量名 map[keytype]valuetype key可以是什么类型 golang中的map,的key可以是很多中类型,比如bool,数字,string,指针,channel,还可以是包含前面几个类型的 接口,结构体,数组 通常为int,string valuetype 可以是什么类型 valuetype的类型和key基本一样,这里我就

  • golang中值类型/指针类型的变量区别总结

    前言 值类型:所有像int.float.bool和string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中.当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝.可以通过 &i 获取变量 i 的内存地址 指针类型:简单地说go语言的指针类型和C/C++的指针类型用法是一样的,除了出去安全性的考虑,go语言增加了一些限制,包括如下几条: 不同类型的指针不能互相转化,例如*int, int32, 以及int

  • 关于Golang中range指针数据的坑详解

    前言 在Golang中使用 for range 语句进行迭代非常的便捷,但在涉及到指针时就得小心一点了. 下面的代码中定义了一个元素类型为 *int 的通道 ch : package main import ( "fmt" ) func main() { ch := make(chan *int, 5) //sender input := []int{1,2,3,4,5} go func(){ for _, v := range input { ch <- &v } cl

  • golang中range在slice和map遍历中的注意事项

    golang中range在slice和map遍历中的注意事项 package main import ( "fmt" ) func main() { slice := []int{0, 1, 2, 3} myMap := make(map[int]*int) for _,v :=range slice{ if v==1 { v=100 } } for k,v :=range slice{ fmt.Println("k:",k,"v:",v) }

  • Golang Map实现赋值和扩容的示例代码

    golang map 操作,是map 实现中较复杂的逻辑.因为当赋值时,为了减少hash 冲突链的长度过长问题,会做map 的扩容以及数据的迁移.而map 的扩容以及数据的迁移也是关注的重点. 数据结构 首先,我们需要重新学习下map实现的数据结构: type hmap struct { count int flags uint8 B uint8 noverflow uint16 hash0 uint32 buckets unsafe.Pointer oldbuckets unsafe.Poin

  • golang 中的 nil的场景分析

    源码中的 nil 是这样定义的 // nil is a predeclared identifier representing the zero value for a // pointer, channel, func, interface, map, or slice type. var nil Type // Type must be a pointer, channel, func, interface, map, or slice type 所以 nil 可以理解为这些类型的零值,声明

随机推荐