go

golang 50处陷阱

2021-01-01  本文已影响0人  voidFan

golang 50处陷阱

1.main()函数后面的大括号不能放在单独的一行

2.如果存在未使用的变量,将导致编译失败, 可以使用"_ = value"进行注释

3.如果存在未使用的import,会导致编译失败

4.简式的变量声明仅可以在函数内部使用

5.一个代码块内不用简式重复声明变量, 使用":="声明变量时,左边至少有一个变量未声明过

6.偶然的变量隐藏Accidental Variable Shadowing

package main
import "fmt"
func main() {  
    x := 1
    fmt.Println(x)     //prints 1
    {
        fmt.Println(x) //prints 1
        x := 2
        fmt.Println(x) //prints 2
    }
    fmt.Println(x)     //prints 1 (bad if you need 2)
}

不使用显式类型,无法使用“nil”来初始化变量

package main
func main() {  
    var x = nil //error
    var x interface{} = nil //ok
    _ = x
}

使用“nil” Slices and Maps

package main
func main() {  
    var s []int
    s = append(s,1)   //ok
    var m map[]int
    m["one"] = 1      //error
}

map的容量:可以在map创建时指定它的容量,但你无法在map上使用cap()函数

字符串不会为nil

package main
func main() {  
    var x string = nil   //error
    if x == nil {        //error
        x = "default"
    }

    var x string         //defaults to "" (zero value)
    if x == "" {
        x = "default"
    }
}

数组作为函数的参数

package main
import "fmt"
func main() {  
    x := [3]int{1,2,3}
    func(arr [3]int) {    
        arr[0] = 7
        fmt.Println(arr) //prints [7 2 3]
    }(x)
    fmt.Println(x) //prints [1 2 3] (not ok if you need [7 2 3])

    //可以通过传指针的方式实现:func(arr *[3]int) {...}(&x)
    //另外如果只是修改数据,可以使用slice
}

数组和切片使用range语句遍历会得到两个值

数组和切片是一维的

package main
func main() {  
    x := 2
    y := 4
    table := make([][]int,x)
    for i:= range table {
        table[i] = make([]int,y)
    }
}
package main
import "fmt"
func main() {  
    h, w := 2, 4
    raw := make([]int,h*w)
    for i := range raw {
        raw[i] = i
    }
    fmt.Println(raw,&raw[4])
    //prints: [0 1 2 3 4 5 6 7] <ptr_addr_x>
    table := make([][]int,h)
    for i:= range table {
        table[i] = raw[i*w:i*w + w]
    }
    fmt.Println(table,&table[1][0])
    //prints: [[0 1 2 3] [4 5 6 7]] <ptr_addr_x>
}

访问不存在的Map Keys

package main
import "fmt"
func main() {  
    x := map[string]string{"one":"a","two":"","three":"c"}
    if v := x["two"]; v == "" { //incorrect
        fmt.Println("no entry")
    }
}
////////////////////////////////////////////////////////////
func main() {  
    x := map[string]string{"one":"a","two":"","three":"c"}
    if _,ok := x["two"]; !ok {  //good
        fmt.Println("no entry")
    }
}

Strings无法修改

package main
import "fmt"
func main() {  
    x := "text"
    x[0] = 'T'    //Compile Error:
    fmt.Println(x)
}
/////////////////////////////////////
func main() {  
    x := "text"
    xbytes := []byte(x)
    xbytes[0] = 'T'
    fmt.Println(string(xbytes)) //prints Text
}

注意:这并不是在文字string中更新字符的正确方式,因为给定的字符可能会存储在多个byte中。如果你确实需要更新一个文字> > string,先把它转换为一个rune slice。即使使用rune slice,单个字符也可能会占据多个rune,比如当你的字符有特定的重音> 符号时就是这种情况。这种复杂又模糊的“字符”本质是Go字符串使用byte序列表示的原因。

String和Byte Slice之间的转换

  1. 第一个优化避免了当[]byte keys用于在map[string]集合中查询时的额外分配:m[string(key)]。
  2. 第二个优化避免了字符串转换为[]byte后在for range语句中的额外分配:for i,v := range []byte(str) {...}

17. String和索引操作

package main
import "fmt"
func main() {  
    x := "text"
    fmt.Println(x[0]) //print 116
    fmt.Printf("%T",x[0]) //prints uint8
}

18. 字符串不总是UTF8文本

上一篇下一篇

猜你喜欢

热点阅读