1. for range

  • for-range其实是语法糖,内部调用还是for循环,初始化会拷贝带遍历的列表(如array,slice,map),然后每次遍历的v都是对同一个元素的遍历赋值。 也就是说如果直接对v取地址,最终只会拿到一个地址,而对应的值就是最后遍历的那个元素所附给v的值。对应伪代码如下:
  1. package main
  2. import "fmt"
  3. func main() {
  4. slice := []int{0, 1, 2, 3}
  5. myMap := make(map[int]*int)
  6. for index, value := range slice {
  7. myMap[index] = &value
  8. }
  9. prtMap(myMap)
  10. }
  11. func prtMap(myMap map[int]*int) {
  12. for key, value := range myMap {
  13. fmt.Printf("map[%v]=%v\n", key, *value)
  14. }
  15. }

输出

  1. map[3]=3
  2. map[0]=3
  3. map[1]=3
  4. map[2]=3

修正

  1. package main
  2. import "fmt"
  3. func main() {
  4. slice := []int{0, 1, 2, 3}
  5. myMap := make(map[int]*int)
  6. for index, value := range slice {
  7. num := value
  8. myMap[index] = &num // &slice[index] 也可以,去掉value
  9. }
  10. prtMap(myMap)
  11. }
  12. func prtMap(myMap map[int]*int) {
  13. for key, value := range myMap {
  14. fmt.Printf("map[%v]=%v\n", key, *value)
  15. }
  16. }

输出

  1. map[2]=2
  2. map[3]=3
  3. map[0]=0
  4. map[1]=1

2. 遍历会停止么

  1. v := []int{1, 2, 3}
  2. for i := range v {
  3. v = append(v, i)
  4. }

【会】,因为遍历前对v做了拷贝,所以期间对原来v的修改不会反映到遍历中

3. 对大数组这样遍历有啥问题?

  1. //假设值都为1,这里只赋值3个
  2. var arr = [102400]int{1, 1, 1}
  3. for i, n := range arr {
  4. //just ignore i and n for simplify the example
  5. _ = i
  6. _ = n
  7. }

【有问题】!遍历前的拷贝对内存是极大浪费啊 怎么优化?有两种 - 对数组取地址遍历 for i, n := range &arr - 对数组做切片引用 for i, n := range arr[:]

4. 零切片和nil切片


  1. ```go package main

import “fmt”

func main() { var s1 []int // nil 切片 var s2 = []int{}

  1. fmt.Println(s1 == nil)
  2. fmt.Println(s2 == nil)
  3. fmt.Printf("%#v\n", s1)
  4. fmt.Printf("%#v\n", s2)

}


true false []int(nil) []int{}

  1. 2. <br />
  2. ```go
  3. type Something struct {
  4. values []int
  5. }
  6. var s1 = Something{}
  7. var s2 = Something{[]int{}}
  8. fmt.Println(s1.values == nil)
  9. fmt.Println(s2.values == nil)
  10. --------
  11. true
  12. false

  1. ```go type Something struct { Values []int }

var s1 = Something{} var s2 = Something{[]int{}} bs1, := json.Marshal(s1) bs2, := json.Marshal(s2) fmt.Println(string(bs1)) fmt.Println(string(bs2))


{“Values”:null} {“Values”:[]}

  1. <a name="K3mUx"></a>
  2. #### 5. Add函数一定要在Wait函数执行前执行
  3. <a name="IofSg"></a>
  4. #### 函数声明
  5. ```go
  6. package main
  7. import "fmt"
  8. func DeferFunc1(i int) (t int) {
  9. fmt.Println("t = ", t)
  10. return 2
  11. }
  12. func main() {
  13. DeferFunc11(10)
  14. }
  1. t = 0

证明,只要声明函数的返回值变量名称,就会在函数初始化时候为之赋值为0,而且在函数体作用域可见

6 Go语言字符串的字节长度和字符个数

  1. func main() {
  2. str := "Golang罗尔"
  3. fmt.Println(len(str)) // 12
  4. fmt.Println(len([]rune(str))) // 8
  5. }

如果有中文字符判断的话,需要转

计算机只能处理数字,如果想要处理文本需要转换为数字才能处理,早些时候,计算机在设计上采用8bit作为一个byte,一个byte表示的最大整数就是255,想表示更大的整数,就需要更多的byte。

len()函数是用来获取字符串的字节长度,rune一个值代表的就是一个Unicode字符,所以求rune切片的长度就是字符个数。因为在utf-8编码中,英文占1个字节,中文占3个字节,所以最终结果就是15和9。