加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Go实战--golang新手入门常见错误(The way to go)

发布时间:2020-12-16 18:13:02 所属栏目:大数据 来源:网络整理
导读:生命不止,继续 go go go !!! 今天分享的是在学习、应用golang过程中,遇到的哪些错误。 左大括号不能单独一行 曾经的曾经,我们经常讨论{是在上一行的末尾,还是另起一行,也因为这个区别我们分成了左派还是右派。 对于诸如C++等语言来说,无论选择哪一

生命不止,继续 go go go !!!

今天分享的是在学习、应用golang过程中,遇到的哪些错误。

左大括号不能单独一行
曾经的曾经,我们经常讨论{是在上一行的末尾,还是另起一行,也因为这个区别我们分成了左派还是右派。

对于诸如C++等语言来说,无论选择哪一种格式,只是形式不同罢了,没有对错之分。但是,对于golang就不一样了,golang中{不能单独一行:

package main

import "fmt"

func main()  
{  //错误
    fmt.Println("hello gopher!")
}

未使用的变量会报错,但是未使用的全局变量是不会报错的
在其他语言中,你声明了一个变量,但是没有使用它,也许是一件很轻松平常的事儿,但是对于golang来说,这就是灾难:

package main

var gvar int //不会报错

func main() {  
    var one int   //未使用,错误
    two := 2      //未使用,错误
    var three int //即使被赋值了,但是未使用,错误
    three = 3

    func(unused string) {
        fmt.Println("Unused arg. No compile error")
    }("what?")
}

未使用的导入package
在C++中,不严谨的工程师会乱引入一些不需要的库,但是golang是不行的,gopher的世界中不允许这么不严谨的人存在:

package main

import (  
    "fmt"
)

func main() {  
}

短变量声明只能在函数体内
在C++11后,给我们提供了auto关键字,用于自动推断变量的类型。在golang中没有这样的关键字,但是有短变量格式,可以不用显示的声明变量的类型。
但是,全局变量是不可以使用这种方式的。
同样,不可以重新声明已经声明过的短变量。

package main

import (  
    "fmt"
)

myvar := 1 //错误

func main() {  
    a := 100 //短变量
    a := 101 //错误
    a,b := 101, 202 //是可以的,:=左边至少有一个是新声明的
    fmt.Println(a)
    fmt.Println(b)
}

不能使用nil显示的初始化变量
The “nil” identifier can be used as the “zero value” for interfaces,functions,pointers,maps,slices,and channels.
看到了吧,nil可以干这么多事儿,但是不能把一个变量显示的声明为nil:

package main

func main() {  
    var x = nil //错误
    var y interface{} = nil //可以
    var z string = nil //错误

    _ = x
    _ = y
    _ = z
}

空在slice和map中的不同
对于空的slice,可以添加item,但是对于空的map是不可以的:

package main

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

    var m map[string]int
    m["one"] = 1 //错误
}

不能将cap内置函数用于map

package main

func main() {  
    m := make(map[string]int,99)
    cap(m) //错误
}

数组作为函数参数传递不会退化为指针
C++程序员知道,数组名作为函数参数的时候,退化为指针,也就是不会副本。
但是,golang的世界变了,数组也是以副本的形式作为形参的:

package main

import "fmt"

func main() {  
    x := [3]int{1,2,3}

    func(arr [3]int) {
        arr[0] = 0
        fmt.Println(arr) //输出 [0 2 3]
    }(x)

    fmt.Println(x) //输出 [1 2 3]
}

用slice代替数组作为函数参数,slice是引用类型
其实,在golang中,很少很少使用数组,也要谨慎,我们可以使用slice来代替数组完成上面的代码:

package main

import "fmt"

func main() {  
    x := []int{1,3}

    func(arr []int) {
        arr[0] = 0
        fmt.Println(arr) //输出 [0 2 3]
    }(x)

    fmt.Println(x) //输出 [0 2 3]
}

使用range遍历遇到的坑儿
c++11中增加了基于范围的for循环,foreach,但是在golang中有range,我们先看代码:

package main

import "fmt"

func main() {  
    x := []string{"a","b","c"}

    for v := range x {
        fmt.Println(v) //输出 0,1,2
    }
}

你原本想输出 a b c ,但是却输出了 0 1 2,很显然是输出了a b c 所对应的index。遇到这个坑就是对range理解的不够深刻而已,range远远比你想象的更牛,他会同时返回value和index。
这也是golang中函数的特性,可以返回多余一个的返回值!!!!
正确的代码:

package main

import "fmt"

func main() {  
    x := []string{"a","c"}

    for _,v := range x {
        fmt.Println(v) //输出 a,b,c
    }
}

在string上使用index索引
首先要明确string是不可变的!!!!

package main

import "fmt"

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

通过len获取字符串的长度

package main

import "fmt"

func main() {  
    data := "?"
    fmt.Println(len(data)) //prints: 3
}

使用switch遇到的坑儿
在C++中,我们知道,在switch语句中,case后如果没有break,就会顺序执行。
但是在golang的switch中,我们不需要显示的使用break关键字,也不会顺序执行:

package main

import "fmt"

func main() {  
    isSpace := func(ch byte) bool {
        switch(ch) {
        case ' ': //错误
        case 't':
            return true
        }
        return false
    }

    fmt.Println(isSpace('t'))
    fmt.Println(isSpace(' '))
}

我们可以使用fallthrough,也可以一个case后面写多余一个的值:

package main

import "fmt"

func main() {  
    isSpace := func(ch byte) bool {
        switch(ch) {
        case ' ','t':
            return true
        }
        return false
    }

    fmt.Println(isSpace('t'))
    fmt.Println(isSpace(' '))
}

不允许使用前缀自增
在其他语言中,++i和i++都是允许的,但是golang中只允许使用后缀自增。并且,自增表达式不能用于表达式中:

package main

import "fmt"

func main() {  
    data := []int{1,3}
    i := 0
    ++i //错误
    fmt.Println(data[i++]) //错误
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读