初探go

go语言的基本概念

1. go语言的特性

  • 编译型语言 : 先编译再运行(go build),和C一样的特性,速度快(优于java和python这种解释型语言,java先编译后解释再运行,python解释然后运行)
  • 垃圾回收 : 自动回收垃圾(不需要手动释放内存),和 java 一样
  • 异常处理 : 没有try…catch,用返回值的形式来判断错误
  • 交叉编译 : 可以在不同平台编译(windows,linux,mac),完全支持UTF-8编码
  • 高并发 : 支持高并发(goroutine),很多情况下不需要考虑锁机制带来的问题(channel)
  • 网络编程方便 : 自带了网络编程的接口
  • 短语法: 自动变量类型判断(:=),函数简化(func),访问权限机制由标识符(函数名,变量名,常量名)的首字母大小写来决定(大写public,小写private)
  • 语言交互性 : go 由 C 语言开发,可以调用c语言(cgo)

2. go的一些概念

环境变量

  • GOROOT : go的安装目录
  • GOPATH : 工作目录,包含三个子目录 : bin,pkg,src
  • GOBIN : 编译后二进制文件的存放路径
  • GO111MODULE : 是否开启go mod模式(1.11版本后默认开启)
  • GOARCH : 目标平台的架构(amd64,arm)
  • GOPROXY : Go 的代理设置,用于下载 Go 的第三方包

一些命令

  • go build : 编译go文件,生成可执行文件
  • go run : 编译并运行go文件
  • go install : 编译并安装包及其依赖项
  • go get:动态获取远程代码包及其依赖包,并进行编译和安装
  • go mod:用于模块维护,包括初始化模块、添加和更新依赖项等
  • go clean:删除编译生成的对象文件和缓存文件
  • go fmt:使用 gofmt 重新格式化 Go 包的源代码
  • go list:列出包或模块的信息
  • go version:打印 Go 的版本信息
  • go env:打印 Go 的环境信息

3. go语言的语法

书写规范

  • 命名规范:
    Go 在命名时以字母或下划线开头,后面跟着零或更多的字母、下划线和数字
    Go 不允许在命名时中使用 @、$ 和 % 等标点符号
    Go 是一种区分大小写的编程语言,命名以一个大写字母开头,如:Group1,那么使用这种形式的标识符的对象就可以被外部包的代码所使用
  • 代码风格:
    Go 语言的代码风格应该简洁、清晰。
    Go 语言鼓励使用简短的变量名,尤其是在函数的局部变量。

基本类型

  • 基本类型和java还是有挺多不同的,如下

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    bool
    string
    int int8 int16 int32 int64
    uint uint8 uint16 uint32 uint64 uintptr 无符号
    byte // uint8 的别名

    rune // int32 的别名 类似于java中的char类型
    // 表示一个 Unicode 码点

    float32 float64 浮点数类型(C中的float和double)

    complex64 complex128 // 复数类型(在math包中)

    他们的零值:

    1
    2
    3
    4
    5
    数值类型为:0
    布尔类型为:false
    字符串为(空字符串):""
    // go中没有null的概念
    指针、切片、映射、通道、函数和接口等引用类型的零值则是nil
  • 变量和常量:
    go中常量声明用const,变量声明用var或者:=(短变量声明,在函数体内,不能用于全局变量的声明);

导入包(目录)

go导入包步骤: 先去$GOROOT下查找,再去$GOPATH下查找

go导入包 一般用import关键字,如下

1
2
3
4
5
6
7
8
9
10
import "fmt"   // 单行导入
import ( // 多行导入
"fmt"
"math/rand"
)
// 当我们导入了两个具有同一包名的包时产生冲突,可以定义别名
import (
"crypto/rand"
mrand "math/rand" // 将名称替换为mrand避免冲突
)

打印

go中打印使用fmt包,最常用的是PrintfPrintln
Printf支持格式化的字符串(在字符串中添加格式说明符如%T,像c语言的printf一样)
Println会自动在末尾添加换行符(和java的System.out.println差不多,只是拼接字符串和变量用的符号不同,java中用的是+,而go中是,)
如下:

1
2
3
4
5
6
7
8
9
10
11
package main

import (
"fmt"
)

func main() {
var c = -5 + 12i
fmt.Printf("Type=%T\n", c)
fmt.Println("Type=%T", c)
}

go中的格式说明符:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
%v:默认格式的值
%+v:类似 %v,但会包含结构体的字段名
%#v:生成值的Go语法表示
%T:打印值的类型
%s:字符串或者字节数组的无解释字节
%q:单引号围绕的字符字面值,由 Go 语法安全地转义
%d:十进制表示的整数
%b:一个二进制整数,将一个整数格式转化为二进制的表达方式
%o:八进制整数
%x:小写的十六进制数值
%X:大写的十六进制数值
%U:一个 Unicode 表示法表示的整型码值
%f:浮点数
%p:指针,十六进制方式显示

输入

go中输入使用fmt包,最常用的是ScanfScanln,同上,Scanln会自动在末尾添加换行符,Scanf格式化输入
不同的是,输入需要进行异常处理,如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main

import (
"fmt"
)

func main() {
var sum int
_, err := fmt.Scanf("%d", &sum) // _(空白标识符)表示不使用返回值
// _, err := fmt.Scanln(&sum) // 如果用一个变量来接收这个返回值的话,正常是返回1
if err != nil {
fmt.Println(err)
}
fmt.Println(sum)
}

循环

在go中使用for关键字,go中没有while,只有for,如下:

1
2
3
4
5
6
7
for{
// 死循环
}

for i:=0;i<10;i++{
fmt.Println(i)
}
  • for-range
    这是Go语言特有的一种的迭代结构,它一般用来遍历数组,slice和map等集合。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    package main
    import(
    "fmt"
    )
    func main() {
    arr := [...]int{6, 7, 8}
    for i, v := range arr {
    fmt.Println(i,v)
    }
    }
    输出结果:
    1
    2
    3
    0 6
    1 7
    2 8

条件语句

  • if-else,与C语言不同的是,go中的if语句可以添加初始化语句
    如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
        package main

    import "fmt"

    func main() {
    var sum int
    _, err := fmt.Scanln(&sum)
    if err != nil {
    fmt.Println("输入错误")
    }
    if i := 8; sum < i {
    fmt.Println("执行if语句内的打印")
    } else if sum == i {
    fmt.Println("执行else-if语句内的打印")
    } else {
    fmt.Println("执行else语句内的打印")
    }
    }
    ```
    - switch-case
    golang中的`switch`语句与C语言中的`switch`语句类似,但是golang中的`case`语句默认会`break`,不会像C那样没有`break`就一直执行下去
    如下:
    ``` go
    package main

    import "fmt"

    func main() {
    var sum int
    _, err := fmt.Scanln(&sum)
    if err != nil {
    fmt.Println("输入错误")
    }
    switch sum {
    case 1:
    fmt.Println("这是第1个case语句")
    case 2:
    fmt.Println("这是第2个case语句")
    case 3:
    fmt.Println("这是第3个case语句")
    default:
    fmt.Println("这是第default语句")
    }
    }
  • fallthrough关键字
    switch语句中,如果在执行完每个分支的代码后,还希望继续执行后续分支的代码,可以使用fallthrough关键字来达到目的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    package main
    import(
    "fmt"
    )
    func main() {
    i :=2
    switch i {
    case 0:
    fmt.Printf("0")
    case 1:
    fmt.Printf("1")
    case 2:
    fallthrough //fallthrough会强制执行后面的case代码
    case 3:
    fmt.Printf("3")
    default:
    fmt.Printf("Default")
    }
    }

defer关键字

在Go语言中,defer是一种延迟调用机制,defer后面的函数只有在当前函数执行完毕后才能执行

如:

1
2
3
4
5
6
7
8
package main

import "fmt"

func main() {
defer fmt.Println("这是有前面有defer关键字的语句")
fmt.Println("这是没有defer关键字的语句")
}

输出结果为:

1
2
这是没有defer关键字的语句
这是有前面有defer关键字的语句

当有多个defer语句时,后面的defer语句会先执行
如:

1
2
3
4
5
6
7
8
9
10
11
package main

import "fmt"

func main() {
defer fmt.Println("结束")
for i := 0; i < 4; i++ {
defer fmt.Println(i)
}
defer fmt.Println("开始")
}

输出结果为:

1
2
3
4
5
6
开始
3
2
1
0
结束
Contents
  1. 1. go语言的基本概念
    1. 1.1. 1. go语言的特性
    2. 1.2. 2. go的一些概念
      1. 1.2.1. 环境变量
      2. 1.2.2. 一些命令
    3. 1.3. 3. go语言的语法
      1. 1.3.1. 书写规范
      2. 1.3.2. 基本类型
      3. 1.3.3. 导入包(目录)
      4. 1.3.4. 打印
      5. 1.3.5. 输入
      6. 1.3.6. 循环
      7. 1.3.7. 条件语句
      8. 1.3.8. defer关键字
|