Go 常见的 mistake(下)

58 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第14天,点击查看活动详情

i++ 和 ++i

java 中两者是可以支持的,但是go中不支持后者的语法

package main

import "fmt"

func main() {
   slice := []int{1,2,3,4}
   n := 0
   ++n // 编译不通过
   fmt.Println(slice[n++]) // 编译不通过
}

正确写法

func main() {
   slice := []int{1,2,3,4}
   n := 0
   n++
   fmt.Println(slice[n+1])
}

for 循环中使用变量和闭包

for语句中的迭代变量用的是同一个地址,在每次迭代时被重新使用,所以你在for循环中创建的闭包将会引用同一个变量

package main

import (  
    "fmt"
    "time"
)

func main() {  
    data := []string{"one","two","three"}

    for _,v := range data {
        go func() {
            fmt.Println(v)
        }()
    }

    time.Sleep(3 * time.Second)
    //result -> three, three, three
}

正确用法1:

用短式赋值表达式重新开辟空间,这样用的就不是同一个地址了


package main

import (
"fmt"
"time"
)

func main() {
   data := []string{"one","two","three"}

   for _,v := range data {
      v := v
      go func() {
         fmt.Println(v)
      }()
   }

   time.Sleep(3 * time.Second)
}

正确用法2:

把当前迭代的变量作为goroutine的参数

package main

import (  
    "fmt"
    "time"
)

func main() {  
    data := []string{"one","two","three"}

    for _,v := range data {
        go func(in string) {
            fmt.Println(in)
        }(v)
    }

    time.Sleep(3 * time.Second)
  
}

使用指针接收方法的值的实例

只要对象的地址是被创建的,存在的,那么可以调用这个指针接收的方法 使用 d1 := data{"one"}等于 var in printer = &data{"two"}

package main


import "fmt"

type data struct {
   name string
}

func (p *data) print() {
   fmt.Println("name:",p.name)
}

type printer interface {
   print()
}

func main() {
   d1 := data{"one"}
   d1.print() //ok

   var in printer = data{"two"} //error
   in.print()

   m := map[string]data {"x":data{"three"}}
   m["x"].print() //error
}

正确如下:

package main


import "fmt"

type data struct {
   name string
}

func (p *data) print() {
   fmt.Println("name:",p.name)
}

type printer interface {
   print()
}

func main() {
   d1 := data{"one"}
   d1.print() //ok

   var in printer = &data{"two"}
   in.print()

   m := map[string]data {"x":data{"three"}}
   d := m["x"]
   d.print()
}

更新map的值

下面编译错误因为map元素是无法取址的

package main

type data struct {  
    name string
}

func main() {  
    m := map[string]data {"x":{"one"}}
    m["x"].name = "two" //error
}

正确如下

package main

import "fmt"

type data struct {  
    name string
}

func main() {  
    m := map[string]*data {"x":{"one"}}
    m["x"].name = "two" 
    fmt.Println(m["x"]) 
}