老男孩IT教育,只培养技术精英

全国免费咨询电话:400-609-2893
Go语言常见语法错误

    /    2018-10-24

1. 开大括号不能放在单独的一行

错误代码:

package main
import "fmt"
func main() 
{ 
    fmt.Println("hello world!")
}

编译错误:

./main.go:5:6: missing function body for "main"
./main.go:6:1: syntax error: unexpected semicolon or newline before {

正确代码:

package main
import "fmt"
func main() {
    fmt.Println("hello world!")
}

2. 未使用的变量

如果你有未使用的局部变量,代码将编译失败。

如果你给未使用的变量分配了一个新的值,代码还是会编译失败。你需要在某个地方使用这个变量,才能让编译器愉快的编译。

错误代码:

package main
var gvar int
func main() {
    var one int
    two := 2
    var three int
    three = 3
}

编译错误:

./main.go:6:6: one declared and not used
./main.go:7:9: two declared and not used
./main.go:8:6: three declared and not used

正确代码:

package main
import "fmt"
func main() {
    var one int
    _ = one
    two := 2
    fmt.Println(two)
    var three int
    three = 3
    one = three
    var four int
    four = four
}
// 另外可以选择是注释掉或者移除未使用的变量

3. 未使用的Imports

如果你引入一个包,而没有使用其中的任何函数、接口、结构体或者变量的话,代码将会编译失败。

如果你真的需要引入的包,你可以添加一个"_"下划线标记符,来作为这个包的名字,从而避免编译失败。下滑线标记符用于引入,但不使用。

错误代码:

package main
import (
    "fmt"
    "log"
    "time"
)
func main() {
}

编译错误:

./main.go:4:2: imported and not used: "fmt"
./main.go:5:2: imported and not used: "log"
./main.go:6:2: imported and not used: "time"

正确代码:

package main

import (
    _ "fmt"
    "log"
    "time"
)

var _ = log.Println

func main() {
    _ = time.Now
}

// 另外可以选择是移除或者注释掉未使用的imports

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

错误代码:

package main
myvar := 1 
func main() {  
}

编译错误:

./main.go:3:1: syntax error: non-declaration statement outside function body

正确代码:

package main
var myvar = 1
func main() {
}

5. 使用简式声明重复声明变量

你不能在一个单独的声明中重复声明一个变量,但在多变量声明中这是允许的,其中至少要有一个新的声明变量。

重复变量需要在相同的代码块内,否则你将得到一个隐藏变量。

错误代码:

package main
func main() {
    one := 0
    one := 1
}

编译错误:

./main.go:5:6: no new variables on left side of :=

正确代码:

package main
func main() {
    one := 0
    one, two := 1, 2
    one, two = two, one
}

6. Go语言命名区分大小写

错误代码:

package main
import "fmt"
func main() {
    fmt.println("Hello world")
}
// 以下代码都是不正确的:
// Package main
// iMport "fmt"
// import "Fmt"
// Func main() {}
// Fmt.Println
// fmt.println

编译错误:

./main.go:6:2: cannot refer to unexported name fmt.println
./main.go:6:2: undefined: fmt.println

正确代码:

package main
import "fmt"
func main() {
    fmt.Println("Hello world")
}

7. Go语言中分号分行

错误代码:

package main
import "fmt"
func main() {
    fmt.Println("Hello world") fmt.Println("Hi again")
}

编译错误:

./main.go:6:29: syntax error: unexpected fmt at end of statement

正确代码:

package main
import "fmt"
func main() {
    fmt.Println("Hello world")
    //解决以上问题,可以将上述的两条语句放在两行
    fmt.Println("Hi again") 
    //可以将两条语句用分号结束
    fmt.Println("Hello world");fmt.Println("Hi again") 
    test()
}
func test() { 
    //因此在Go语言中,分号能省则省,如果必须使用时,添加上也不会出错。
    fmt.Println("Hello world");fmt.Println("Hi again");
};

8. Go语言中无效的分号

错误代码:

package main
import "fmt";;
func main() {
    fmt.Println("Hello world")
}

编译错误:

./main.go:3:14: syntax error: non-declaration statement outside function body

正确代码:

package main
import "fmt";
func main() {
    fmt.Println("Hello world")
}

9. Go语言中注意变量作用域

错误代码:

package main
var num int
func main() {
    str := "hello world"
    if true {
        var b bool
    }
    println(num)
    println(str)
    println(b)
}

编译错误:

./main.go:12:10: undefined: b

正确代码:

package main
var num int
func main() {
    str := "hello world"
    if true {
        var b bool
        println(b)
    }
    println(num)
    println(str)
}

10. 偶然的变量隐藏

短式变量声明的语法如此的方便(尤其对于那些使用过动态语言的开发者而言),很容易让人把它当成一个正常的分配操作。如果你在一个新的代码块中犯了这个错误,将不会出现编译错误,但你的应用将不会做你所期望的事情。

package main
import "fmt"
func main() {
    x := 1
    fmt.Println(x) // 1
    {
        fmt.Println(x) // 1
        x := 2
        fmt.Println(x) // 2
    }
    fmt.Println(x) // 1 
}

运行结果:

1
1
2
1

即使对于经验丰富的Go开发者而言,这也是一个非常常见的陷阱,但又很难发现。

你可以使用 vet命令来发现一些这样的问题。 默认情况下, vet不会执行这样的检查,你需要设置-shadow参数:

命令:go tool vet -shadow your_file.go

go tool vet -shadow main.go
main.go:10: declaration of "x" shadows declaration at main.go:6

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

nil标志符用于表示interface、函数、maps、slices和channels的“零值”。如果你不指定变量的类型,编译器将无法编译你的代码,因为它猜不出具体的类型。

错误代码:

package main
func main() {
    var x = nil
    _ = x
}

编译错误:

./main.go:4:6: use of untyped nil

正确代码:

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

12. 使用“nil” Slices and Maps

在一个nil的slice中添加元素是没问题的,但对一个map做同样的事将会生成一个运行时的panic。

正确代码:

package main
func main() {
    var s []int
    s = append(s, 1)
}

错误代码:

package main
import (
    "fmt"
)
func main() {
    var m map[int]int
    m[1] = 1
    fmt.Println(m)
}

运行错误:

panic: assignment to entry in nil map

正确代码:

package main
import (
    "fmt"
)
func main() {
    var m map[int]int
    m = make(map[int]int)
    m[1] = 1
    fmt.Println(m)
}

13. Map的容量

map 只有 len操作, 没有 cap 操作

错误代码:

package main
import (
    "fmt"
)
func main() {
    m := map[int]string{1: "a", 2: "b", 3: "c"}
    cap := cap(m)
    fmt.Println(cap)
}

编译错误:

./main.go:9:12: invalid argument m (type map[int]string) for cap

正确代码:

package main
import (
    "fmt"
)
func main() {
    m := map[int]string{1: "a", 2: "b", 3: "c"}
    len := len(m)
    fmt.Println(len)
}

14. 字符串不会为nil

这对于经常使用nil分配字符串变量的开发者而言是个需要注意的地方。

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

编译错误:

./main.go:4:6: cannot use nil as type string in assignment
./main.go:5:7: invalid operation: x == nil (mismatched types string and nil)

正确代码:

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

(0)

分享至