Golang新手可能会踩的10个坑初级篇

Golang新手可能会踩的10个坑初级篇

首页休闲益智哈喽打地鼠更新时间:2024-06-12

1.左大括号 { 不能单独放一行

在其他大多数语言中,{ 的位置你自行决定。Go比较特别,遵守分号注入规则(automatic semicolon injection):编译器会在每行代码尾部特定分隔符后加;来分隔多条语句,比如会在 ) 后加分号:

// 错误示例 func main() { println("www.topgoer.com是个不错的go语言中文文档") } // 等效于 func main(); // 无函数体 { println("hello world") }

./main.go: missing function body ./main.go: syntax error: unexpected semicolon or newline before {

// 正确示例 func main() { println("www.topgoer.com是个不错的go语言中文文档") }

2.未使用的变量

如果在函数体代码中有未使用的变量,则无法通过编译,不过全局变量声明但不使用是可以的。即使变量声明后为变量赋值,依旧无法通过编译,需在某处使用它:

// 错误示例 var gvar int // 全局变量,声明不使用也可以 func main() { var one int // error: one declared and not used two := 2 // error: two declared and not used var three int // error: three declared and not used three = 3 } // 正确示例 // 可以直接注释或移除未使用的变量 func main() { var one int _ = one two := 2 println(two) var three int one = three var four int four = four }

3.未使用的 import

如果你 import一个包,但包中的变量、函数、接口和结构体一个都没有用到的话,将编译失败。可以使用 _下划线符号作为别名来忽略导入的包,从而避免编译错误,这只会执行 package 的 init()

// 错误示例 import ( "fmt" // imported and not used: "fmt" "log" // imported and not used: "log" "time" // imported and not used: "time" ) func main() { } // 正确示例 // 可以使用 goimports 工具来注释或移除未使用到的包 import ( _ "fmt" "log" "time" ) func main() { _ = log.Println _ = time.Now }

4.简短声明的变量只能在函数内部使用

// 错误示例 myvar := 1 // syntax error: non-declaration statement outside function body func main() { } // 正确示例 var myvar = 1 func main() { }

5.使用简短声明来重复声明变量

不能用简短声明方式来单独为一个变量重复声明,:=左侧至少有一个新变量,才允许多变量的重复声明:

// 错误示例 func main() { one := 0 one := 1 // error: no new variables on left side of := } // 正确示例 func main() { one := 0 one, two := 1, 2 // two 是新变量,允许 one 的重复声明。比如 error 处理经常用同名变量 err one, two = two, one // 交换两个变量值的简写 }

6.不能使用简短声明来设置字段的值

struct 的变量字段不能使用 := 来赋值以使用预定义的变量来避免解决:

// 错误示例 type info struct { result int } func work() (int, error) { return 3, nil } func main() { var data info data.result, err := work() // error: non-name data.result on left side of := fmt.Printf("info: % v\n", data) } // 正确示例 func main() { var data info var err error // err 需要预声明 data.result, err = work() if err != nil { fmt.Println(err) return } fmt.Printf("info: % v\n", data) }

7.不小心覆盖了变量

对从动态语言转过来的开发者来说,简短声明很好用,这可能会让人误会 := 是一个赋值操作符。如果你在新的代码块中像下边这样误用了 :=,编译不会报错,但是变量不会按你的预期工作:

func main() { x := 1 println(x) // 1 { println(x) // 1 x := 2 println(x) // 2 // 新的 x 变量的作用域只在代码块内部 } println(x) // 1 }

这是 Go 开发者常犯的错,而且不易被发现。可使用 vet工具来诊断这种变量覆盖,Go 默认不做覆盖检查,添加 -shadow 选项来启用:

> go tool vet -shadow main.go main.go:9: declaration of "x" shadows declaration at main.go:5

注意 vet 不会报告全部被覆盖的变量,可以使用 go-nyet 来做进一步的检测:

> $GOPATH/bin/go-nyet main.go main.go:10:3:Shadowing variable `x`

8.显式类型的变量无法使用 nil 来初始化

nil 是 interface、function、pointer、map、slice 和 channel 类型变量的默认初始值。但声明时不指定类型,编译器也无法推断出变量的具体类型。

// 错误示例 func main() { var x = nil // error: use of untyped nil _ = x } // 正确示例 func main() { var x interface{} = nil _ = x }

9.直接使用值为 nil 的 slice、map

允许对值为 nil 的 slice 添加元素,但对值为 nil 的 map添加元素则会造成运行时 panic

// map 错误示例 func main() { var m map[string]int m["one"] = 1 // error: panic: assignment to entry in nil map // m := make(map[string]int)// map 的正确声明,分配了实际的内存 } // slice 正确示例 func main() { var s []int s = append(s, 1) }

10.map 容量

在创建 map 类型的变量时可以指定容量,但不能像 slice 一样使用 cap() 来检测分配空间的大小:

// 错误示例 func main() { m := make(map[string]int, 99) println(cap(m)) // error: invalid argument m1 (type map[string]int) for cap }

查看全文
大家还看了
也许喜欢
更多游戏

Copyright © 2024 妖气游戏网 www.17u1u.com All Rights Reserved