golang 易犯错误事项
1.
func main()
{ // 错误,不能将左大括号放在单独的行上
fmt.Println("hello there!")
}
2.
var gvar int //not an error
func main() {
var one int //error, unused variable
two := 2 //error, unused variable
var three int //error, even though it's assigned 3 on the next line
three = 3
func(unused string) {
fmt.Println("Unused arg. No compile error")
}("what?")
}
3.未使用导入包
import (
"fmt"
"log"
"time"
)
//可以使用空白标识符_作为其包名,以避免此编译失败
func main() {
}
4.
短变量声明只能在函数内部使用
myvar := 1 //error var myvar = 1
func main() {
}
5.
使用短变量声明重新声明变量
func main() {
one := 0
one := 1 //error
}
6.
不能使用短变量声明来设置字段值
type info struct {
result int
}
func work() (int,error) {
return 13,nil
}
func main() {
var data info
data.result, err := work() //error
fmt.Printf("info: %+v
",data)
}
7.
偶然的变量隐藏
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)
}
8.
不能使用 「nil」来初始化没有显式类型的变量
nil标识符可以用作接口,函数,指针,映射,切片和通道的「零值」。如果不指定变量类型,则编译器将无法编译代码,因为它无法猜测类型
func main() {
var x = nil //error
_ = x
}
9
使用 「nil」 切片和映射
正确的
func main() {
var s []int
s = append(s,1)
}
错误的
func main() {
var m map[string]int
m["one"] = 1 //error
}
10
字符串不能为「nil」
func main() {
var x string = nil //error
if x == nil { //error
x = "default"
}
}
11
数组函数参数
Go 中的数组是值,因此当您将数组传递给函数时,这些函数会获取原始数组数据的副本。如果你尝试更新数组数据,则可能会出现问题
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])
}
12
切片和数组「range」子句下的意外值
Go 中的「range」子句不同。它生成两个值:第一个值是索引,而第二个值是数据。
func main() {
x := []string{"a","b","c"}
for v := range x {
fmt.Println(v) //prints 0, 1, 2
}
}
func main() {
x := []string{"a","b","c"}
for _, v := range x {
fmt.Println(v) //prints a, b, c
}
}
13
切片和数组是一维的
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>
}
14.
访问不存在的映射键
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 {
fmt.Println("no entry")
}
}
15
字符串是不可变的
尝试使用索引运算符更新字符串变量中的单个字符将导致失败。字符串是只读字节片 (具有一些其他属性)。如果确实需要更新字符串,则在必要时使用字节片而不是将其转换为字符串类型。
func main() {
x := "text"
x[0] = 'T'
fmt.Println(x)
}
func main() {
x := "text"
xbytes := []byte(x)
xbytes[0] = 'T'
fmt.Println(string(xbytes)) //prints Text
}