快速入门Go(1)

Go·语法 2018-12-31 6964 字 1398 浏览 点赞

前言

这是我学习Go语法的笔记。由于有C和Python的基础,上手Go很快。笔记很粗糙,好在自己够用。

此篇包括了Go相关的:变量声明,分支语句(if,switch),循环语句(for)。涉及关键字var const fallthrough goto range 等。

简单示例

// go语言以包作为管理单位
package main  // 声明包

import "fmt"  // 导入包

func main() {  // 左括号必须与函数名同行
    fmt.Println("hello world")
}

注意事项:

  • 每个文件必须声明包;
  • 程序必须有一个main包。

声明变量

声明变量的四种方式:

func main() {
    var a int
    a = 512
    
    var b int = 513  // 此时类型可以省略,就像声明c一样
    
    var c = 514
    
    d := 515  // 简短声明,让编译器为d自动推导类型
    
    fmt.Println("a =", a)  // 打印语句,类似Python中的print
    fmt.Println("b =", b)
    fmt.Println("c =", c)
    fmt.Println("d =", d)
}
// 输出:
a = 512
b = 513
c = 514
d = 515

同时多个同类型变量的声明:

// 第一种
var a int
var b int

// 第二种
var a, b int

如果多个变量类型不同,可以:

var (
    a int
    b int
    c float64
)
// 或者赋初值
var (
    a int = 512
    b int = 1024
    c float64 = 3.14
)

Go语言中,每个声明的变量如果未被初始化,编译器默认为其设置0值。每个类型都有其对应的0值,但不一定是0。

func main() {
    var num int  // int类型
    var str string  // 字符串类型
    var p *int  // int指针类型

    fmt.Println("a =", num)  // 输出0
    fmt.Println("str =", str)  // 输出空字符串
    fmt.Println("p =", p)  // 输出nil
}
// 输出:
a = 0
str = 
p = <nil>

nil相当于Python中的NULL。

声明常量

关键字const承担常量声明的职责,与var声明变量的用法相同。

const num = 512
// 或者
const num int = 512

注意以下几点:

  • 常量必须在声明的时候赋值;
  • 常量没有简短声明方式(:=);
  • 常量一旦声明,就不可以赋值,否则报错:cannot assign to num

iota枚举

iota为每个常量自动赋值(从0开始),每次赋值后自动累加1。

func main()  {
    const (
        a = iota
        b = iota
        c = iota
    )
    fmt.Printf("a = %d b = %d c = %d", a, b, c)
}
// 输出
a = 0 b = 1 c = 2

多个同一行的变量值相同:

func main()  {
    const (
        a = iota
        b, c, d = iota, iota, iota
        e = iota
    )
    fmt.Printf("a = %d b = %d c = %d d = %d e = %d", a, b, c, d, e)
}

也可以简化代码,只开头写一个iota此时不允许一行多个变量

const (
    a = iota
    b
    c
)

iota遇到const会被重置为0

func main() {
    const (
        a = iota
        b
    )
    const c = iota

    fmt.Printf("a = %d b = %d c = %d", a, b, c)
}
// 输出:
a = 0 b = 1 c = 0

基础类型

布尔类型

Go语言中布尔值的falsetrue全小写,而Python是首字母大写:

func main() {
    var flag bool  // 声明
    fmt.Println("flag =", flag)

    var mark = true  // 声明的同时初始化
    fmt.Println("mark =", mark)
    // 或者
    // mark := true
}
// 输出
flag = false
mark = true

字符型

Go语言中,用单引号表示一个字符 (byte),同时字符类型以数值的方式存储:

func main() {
    var c byte = 'z'
    fmt.Println("c =", c)
}
// 输出
c = 122

如果希望字节正常输出,可以用fmt.Printf

fmt.Printf("c = %c", c)  // %c 是字节占位符

由于字节类型以数值方式存储,所以可以进行加减乘除运算:

func main() {
    var c byte = 'z'

    fmt.Println("c =", c)
    fmt.Println("c + 1 =", c + 1)
    fmt.Println("c - 1 =", c - 1)
    fmt.Println("c / 2 = ", c / 2)
    fmt.Println("c * 2 =", c * 2)
}
// 输出
c = 122
c + 1 = 123
c - 1 = 121
c / 2 =  61
c * 2 = 244

字符串类型

字符串(string)双引号表示:

str := "hello world"

Go语言中,'a'"a"是存在区别的(Python中没有区别)。事实上"a"由两个字符组成:'a'+'\0'

一个字符串可以通过索引的方式来访问:

func main()  {
    str := "hello world"
    fmt.Printf("%c, %c", str[0], str[10])
}
// 输出
h, d

甚至可以像Python那样使用切片:

func main()  {
    str := "hello world"
    fmt.Printf("%s", str[:5])
}
// 输出
hello

输入输出

fmt.Scan()

func main() {
    var str string
    fmt.Scan(&str)  // 无需格式占位符
    fmt.Println(str)
}

fmt.Scanf()

func main() {
    var str string
    fmt.Scanf("%s", &str)  // 需要格式占位符
    fmt.Println(str)
}

fmt.Println()
类似Python中的print()函数。

fmt.Printf()
类似C语言中的printf()函数。

分支语句

if

同其他语言一样,Go语言也有if语句,中规中矩(仅仅是不需要小括号,Python对此也是允许的):

func main() {
    num := 512
    if num == 512 {
        fmt.Println("num的值为512")
    }
}

还有if...else if ... else

func main() {
    var num int
    fmt.Scan(&num)
    if num == 512 {
        fmt.Println("num的值为512")
    } else if num > 512 {
        fmt.Println("num的值大于512")
    } else {
        fmt.Println("num的值小于512")
    }
}

俏皮的是,Go语言中的if语句支持初始化一个语句(if 初始化语句; 条件 {...})比如:

func main() {
    var num int
    fmt.Scan(&num)

    if tmp:= 512; num == tmp {
        fmt.Println("num等于512")
    }
}

switch

Go语言中的swicth与C语言中的switch有一些区别。Go语言中,case的结尾默认带有break,无需用户自己添加:

func main() {
    num := 1
    switch  num {  // 不需要break
    case 0:
        fmt.Println("num等于0")
    case 1:
        fmt.Println("num等于1")  // 进入`case 1`之后执行Println,然后直接跳出switch
    case 2:
        fmt.Println("num等于2")
    default:
        fmt.Println("num等于其他")
    }
}
// 输出
num等于1

也可以是其他类型,如字符串变量:

func main() {
    str := "hello world"
    switch  str {  // 不需要break
    case "bye~bye":
        fmt.Println("bye~bye")
    case "hello":
        fmt.Println("hello")
    case "hello world":
        fmt.Println("hello world")
    default:
        fmt.Println("没有匹配字符串")
    }
}
// 输出
hello world

通过添加fallthrough关键字,使代码进入case之后不要直接跳出switch:

func main() {
    num := 1
    switch  num {  // 不需要break
    case 0:
        fmt.Println("num等于0")
        fallthrough
    case 1:
        fmt.Println("num等于1")
        fallthrough
    case 2:
        fmt.Println("num等于2")
        fallthrough
    default:
        fmt.Println("num等于其他")
    }
}
// 输出
num等于1
num等于2
num等于其他

与C中swicth最大区别,在于条件可以写在case后面:

func main() {
    var num int
    fmt.Scan(&num)
    switch {  // 省略变量
    case num > 512:  // 加上条件
        fmt.Println("num大于512")
    case num == 512: 
        fmt.Println("num等于512")
    default:
        fmt.Println("num小于512")
    }
}

循环语句

Go语言只有for循环,没有while,用法如下:

func main() {
    for num:=0; num < 3; num++ {
        fmt.Println(num)
    }
}

可以省略第一个表达式,但需要保留分号;

func main() {
    num := 0
    for ; num < 3; num++ {
        fmt.Println(num)
    }
}

事实上for可以当作while来使用:

num := 0
for  num < 3 {
    num++
    fmt.Println(num)
}

如果什么都不加,就是死循环:

for {
    fmt.Println("这是一个死循环。")
}

关键字range实现迭代效果,如:

func main() {
    str := "hello"
    // 第一个元素是索引值,第二个是索引出来的内容
    for i, alpha := range str {
        fmt.Printf("num = %d, alpha = %c\n", i, alpha)
    }
}

上述代码中alpha可以省略,只需要获取索引值即可:

func main() {
    str := "hello"
    for i := range str {
        fmt.Printf("num = %d, alpha = %c\n", i, str[i])
    }
}

这跟Python中的enumerate()函数有些相似。

跳转语句

如同C语言,Go语言也有goto关键字,用法相同:

func main() {
    fmt.Println("start ...")
    goto End  // 执行到这儿之后不会执行下面的代码,而是执行End之后的代码
    fmt.Println("first end ...")

    End:
    fmt.Println("second end ...")
}
// 输出
start ...
second end ...

goto不能跨函数使用。



本文由 Guan 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论