Go 语言入门指南:基础语法(2) | 青训营

50 阅读4分钟

1.流程控制

1.1 if语句

Go语言中的if语句和其他语言中的if语句十分相似。最明显的区别是不需要在条件的两端加上括号。
具体示例:

if n>0 {

    fmt.Println("n是正数")
}else if n==0{
    fmt.Println("n是0")
}else {
    fmt.Println("n是负数")
}

//还可以赋值后判断
if err=isCorrect();err!=nil{
    
   return

}

1.2 for

在go语言中for是唯一的循环语句关键字


for i:=0;i<10;i++{

    fmt.Println(i)
}

i:=1
for ;i<10;i++{

    fmt.Println(i)
}
i:=1
for ;;i++{

    if i>10{
        return
    }
}
for {
    fmt.Println("无限循环")
}

1.3 for-range

使用for-range可以快速遍历数组,切片和映射

    a:=[]int{1,2,3,4,5}
    for i,v:=range a{
        fmt.Println(i,v)
    
    }

第一个变量是数据在整个被迭代数据中的位置,第二个变量是该位置的值。

2.函数

2.2函数定义


    fun div(a int,b int) int{
        if b==0{
            return 0
        }
        return a/b
    
    }

如以上代码所示,函数声明有4部分:关键字func、函数名、传入参数和返回类型。传入参数被圆括号包括,每个参数名称在前,类型在后,中间用逗号分隔。Go是一种强类型语言,所以必须指定参数的类型。返回类型写在输入参数的右括号和函数体的左大括号之间。

与其他语言一样,Go用return关键字从函数返回值。如果函数返回了某个值,则必须声明返回值。如果函数不返回任何内容,则不需要在函数末尾使用return语句。return关键字也可以在不返回任何内容的函数中使用,即函数执行到最后一行之前就退出该函数。

和其他语言一样,go支持可变长参数,只要在类型前面用三个点(...)来表示。

//多返回值
fun div(a int,b int) (int,int,error){
        if b==0{
            return 0,0,errors.New("不能/0")
        }
        return a/b,a%b,nil
    
    } 

2.2 匿名函数

我们不仅可以将函数赋值给变量,还可以在函数中定义新函数并将它们赋值给变量。

    func main(){
    
        for i:=0;i<10;i++{
            fun (j int) {
            
                fmt.Println("print",j)
            }(i)
        }
    }
    
    //结果print0,print1,print2...
    

2.3 defer

defer语句会在函数执行完后执行,因此可以用来做一些释放资源的工作。

    f,err:=os.Open(os.Args[1])
    if err!=nil{
        log.Fatal(err)
    }
    defer f.Close()

3.指针

和C语言一样,go支持指针,可以通过&来取地址,* 来获取值。但是go语言是不支持指针运算。 指针的行为给人的感觉更像是类。感兴趣可以自己深入去了解下!

4.方法,接口

4.1

Go支持在自定义类型中定义方法。
一个类型的方法是在包代码块级别定义的:

    
    type Person struct{
    
        Name string
        Age int
    }
    
    fun(p Person) String() string{
        return fmt.Sprintf("%s ,age %d",p.Name,p.Age)
    }

看起来与函数的定义很类似,其实就是多了一个接收者说明,也就是func与方法名之间的东西。
和函数一样,方法不支持重载,所以不能对同一类型的两个方法使用相同的方法名。

我们还可以将该方法赋值给一个变量,或者将其作为参数传递给函数func(int)int。这称为方法值:

    p:=Person{Name:"a",age:18}
    f1:=p.String
    fmt.Println(f1)

方法值有点像闭包,因为它可以访问创建它的实例中字段的值。

4.2 接口

接口声明很简单,使用type关键字

    type Personer interface{
        eat()
    }

满足接口的具体类型必须要实现接口中的定义的方法。
接口通常以er结尾来命名

go语言中的接口是采用隐式的实现,也就是说只要具体类型的方法包含了接口中所定义的方法,那么这个具体类型就是实现了该接口。

空接口

在静态类型语言中,有时需要一种方法来说明一个变量可以存储任何类型的值。这就是Go语言中interface{}的作用:

    
   var i interface{}
   i=10
   i="a"
   i=struct{
       Name string
       Age int
   }{"a",18}

空接口类型只是声明了该变量可以存储任何实现任意方法的类型的值。这恰好与Go中的每个类型相匹配

5.错误

Go通过返回一个类型为error的值作为函数的最后一个返回值来处理错误。当一个函数正确执行后,错误对应的返回值就是nil,而如果发生了任何问题,就会返回一个错误值。调用函数之后将错误值与nil进行比较,要么处理错误,要么根据这个错误返回一个自定义错误。
比如之前的除法案例:

fun div(a int,b int) (int,int,error){
        if b==0{
            return 0,0,errors.New("不能/0")
        }
        return a/b,a%b,nil
    
    }