Go学习day2 | 青训营

81 阅读6分钟

Go基础语法学习day2

数组

和c语言相同,Go语言也提供了数组类型的数据结构,数组是具有相同唯一类型的一组已编号且长度固定的数据项序列,这种类型可以是任意的原始类型例如整型、字符串或者自定义类型。

Go中的数组是值传递

  • 声明:var variable_name [SIZE] variable_type
var balance [10] float32
  • 初始化:

    • 直接进行初始化:var balance = [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    • 通过字面量在声明数组的同时快速初始化数组:balance := [5]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    • 数组长度不确定,编译器通过元素个数自行推断数组长度,在[ ]中填入...var balance = [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}balance := [...]float32{1000.0, 2.0, 3.4, 7.0, 50.0}
    • 数组长度确定,指定下标进行部分初始化:balanced := [5]float32(1:2.0, 3:7.0)
  • 在c语言中我们知道数组名在本质上是数组中第一个元素的地址,而在go语言中,数组名仅仅表示整个数组,是一个完整的值,一个数组变量即是表示整个数组。

  • 数组指针:除了可以防止数组作为参数传递的时候浪费空间,还可以利用其和for range来遍历数组

var a = [...]int{1, 2, 3} // a 是一个数组
var b = &a                // b 是指向数组的指针
for i, v := range b {     // 通过数组指针迭代数组的元素
    fmt.Println(i, v)
}

结构体

  • 声明:type用于设定结构体的名称,struct用于定义一个新的数据类型。
type struct_variable_type struct {
   member definition
   member definition
   ...
   member definition
}

函数

/*函数声明
函数声明以func关键字开头,后跟functionname(函数名)。参数在()之间声明,后面是函数的returntype(返回值类型)。
参数声明的语法是参数名称后面跟类型(parametername type)。可以声明任意数量的参数:(parameter1 type, parameter2 type);如果连续的参数是同一类型的,不需要每次都写类型,只需写最后一次就可以,如(parameter1, parameter2 type)。
也可以从一个函数返回多个值:(returntype1, returntype2)。
参数和返回类型在函数中是可选的
*/
func functionname(parametername type) returntype {  
 //function body
}
  • 可以对函数返回值命名。如果命名了返回值,可以将其视为在函数第一行中声明的变量。
/*
面积(area)和周长(perimeter)是函数的返回值,函数中的return语句没有显式地返回任何值。
由于函数声明中命名了返回值:面积(area)和周长(perimeter),所以当遇到返回语句return时,它们将自动从函数中返回。
如果连续的返回值是同一类型的,不需要每次都写类型,只需写最后一次就可以。
*/
func rectProps(length, width float64)(area, perimeter float64) {  
    area = length * width
    perimeter = (length + width) * 2
    return // 没有显式地返回值
}

  • 主函数与主包
/*
package main 声明该源文件属于主包。
import "fmt" 用于导入包fmt,该包中包含了函数Println方法。
func main() {...} 是主函数,打印一行字符串。
*/
package main 
​
import "fmt"func main() {  
    fmt.Println("Geometrical shape properties")
}
  • 导入包:import path
/*
当前文件夹结构:
src  
    geometry
        geometry.go
        rectangle
            rectprops.go
*/
package main 
​
import (  
    "fmt"
    "geometry/rectangle" //导入自定义包
)
​
func main() {  
    var rectLen, rectWidth float64 = 6, 7
    fmt.Println("Geometrical shape properties")
    //使用rectangle包中的函数
    fmt.Printf("area of rectangle %.2f\n", rectangle.Area(rectLen, rectWidth))
    fmt.Printf("diagonal of the rectangle %.2f ",rectangle.Diagonal(rectLen, rectWidth))
}
  • 导出名称

任何以大写字母开头的变量或函数,都将在go中导出名称。

/*
只有导出的函数和变量可以从其他包中访问。我们需要从主包调用Area与Diagonal函数,所以函数名的首字母大写,导出这2个函数。
如果把rectprops.go中的Area(len, wid float64)更改为area(len, wid float64),编译器将报错。
因此,如果想从外部调用包函数,函数首字母应该大写。
*/
  • 包初始化函数
  • 空白标识符 _
/*
在Go中导入一个包而不使用是非法的,编译器会报错。这样可以避免未用包的膨胀,减少编译时间。
使用代码var _ = rectangle.Area消除错误。
这些类型的错误静默器在开发结束时应该删除(包括未使用的导入包)。因此,建议紧跟import语句之后,编写错误静默器。
*/
package main
​
import (  
    "geometry/rectangle" 
)
​
var _ = rectangle.Area // 消除错误func main() {
​
}
/*
有时需要初始化一个包,即使不使用包中的函数或变量。例如,我们需要初始化rectangle包(即调用它的init函数),在这种情况下也可以使用_空白标识符
*/
package main 
​
import (   
     _ "geometry/rectangle" 
)
func main() {
​
}

if

/*
与C等其他语言不同,即使在{}之间只有一条语句,{}也是强制性的
*/
if condition {  
} else if condition {
} else {
}
/*
if还有一个变体,它包含一个可选的语句模块,该模块在条件求值之前执行。它的语法是
if statement; condition {  
    
}
在xia面的程序中,num 在 if 语句中初始化。需要注意的一点是,num 只能从 if 和 else 内部访问。也就是说,num 的范围仅限于 if else 块。如果我们试图从 if 或 else 外部访问 num,编译器就会报错。
*/
package main
​
import (  
    "fmt"
)
​
func main() {  
    if num := 10; num % 2 == 0 { // 检测是否偶数
        fmt.Println(num,"is even") 
    }  else {
        fmt.Println(num,"is odd")
    }
}

循环

for是Go中唯一可用的循环语句。Go没有whiledo while循环

  • for initialisation; condition; post {  
        
    }
    
    • initialisation 初始化语句,只执行一次
    • condition 条件语句
    • post 后期语句将在循环的每次成功迭代后执行

    先执行初始化语句,只执行一次。然后执行条件语句,检查条件,如果为true,则执行{}中的循环体。如果循环体成功执行完毕,接着就会执行post语句。

    post语句执行后,将重新检查条件。如果为真,则循环将继续执行,否则for循环将终止。

    在go中,初始化、条件和后期这三部分都是可选的。

    在for循环中声明的变量只在循环范围内可用。所以循环体之外不能访问i值。

  • break、continue 用法同其他语言

  • 标签

/*
使用标签将外部循环从内部for循环中中断
*/
package main
​
import (  
    "fmt"
)
​
func main() {  
outer:  
    for i := 0; i < 3; i++ {
        for j := 1; j < 4; j++ {
            fmt.Printf("i = %d , j = %d\n", i, j)
            if i == j {
                break outer
            }
        }
​
    }
}
  • for循环分号可以省略
//可以作为while循环的替代
package main
​
import (  
    "fmt"
)
​
func main() {  
    i := 0
    for i <= 10 { //分号省略,只有条件存在
        fmt.Printf("%d ", i)
        i += 2
    }
}
  • for循环中声明和操作多个变量
package main
​
import (  
    "fmt"
)
​
func main() {  
    for no, i := 10, 1; i <= 10 && no <= 19; i, no = i + 1, no + 1 { //多个变量初始化,多个增量
        fmt.Printf("%d * %d = %d\n", no, i, no*i)
    }
}
  • 无限循环
for {  
    
}

switch

  • 没有case穿透,不需要用break
  • 不允许重复使用相同的常数值
package main
​
import (  
    "fmt"
)
​
func main() {  
    finger := 4
    switch finger {
    case 1:
        fmt.Println("Thumb")
    case 2:
        fmt.Println("Index")
    case 3:
        fmt.Println("Middle")
    case 4:
        fmt.Println("Ring")
    case 4://duplicate case
        fmt.Println("Another Ring") //error
    case 5:
        fmt.Println("Pinky")
    }
}
  • default不一定放在最后,它可以出现在switch语句中的任何地方
package main
​
import (  
    "fmt"
)
//switch 语句可以包含一个可省略语句,它在表达式求值之前执行,此处声明的 finger 变量作用域,仅限于 switch 语句包含的代码块。
func main() {  
    switch finger := 8; finger {
    case 1:
        fmt.Println("Thumb")
    case 2:
        fmt.Println("Index")
    case 3:
        fmt.Println("Middle")
    case 4:
        fmt.Println("Ring")
    case 5:
        fmt.Println("Pinky")
    default: //default case
        fmt.Println("incorrect finger number")
    }
}
  • case中可以包含多个表达式,用逗号分隔。
package main
​
import (  
    "fmt"
)
​
func main() {  
    letter := "i"
    switch letter {
    case "a", "e", "i", "o", "u": //letter匹配其中的一个就行
        fmt.Println("vowel")
    default:
        fmt.Println("not a vowel")
    }
}
  • switch语句中的表达式是可选的,可以省略。如果表达式被省略,则认为switchtrue,并对每个case表达式求值,为真则执行相应的代码块。等价于多个if else子句
package main
​
import (  
    "fmt"
)
​
func main() {  
    num := 75
    switch { // expression is omitted
    case num >= 0 && num <= 50:
        fmt.Println("num is greater than 0 and less than 50")
    case num >= 51 && num <= 100:
        fmt.Println("num is greater than 51 and less than 100")
    case num >= 101:
        fmt.Println("num is greater than 100")
    }
​
}