Go语言基础知识!

官方网站:

中文网在线标准库文档:

Google创造Go语言的目的:

计算机硬件技术更新频繁:

  • 性能提高很快,目前主流的编程语言发展落后于硬件
    • 不能合理利用多核CPU的优势提升软件系统性能

软件系统复杂度越来越高,维护成本越来越高

  • 目前缺乏一个足够简洁高效的编程语言

企业运行维护很多C/C++的项目,C/C++程序运行速度很快,但是编译速度很慢

  • 同时还存在内存泄漏的一系列的困扰需要解决

Go岗位

区块链研发工程师

服务器/游戏软件工程师

分布式/云计算软件工程师

Go语言特点

Go语言保证了既能够达到静态编译语言的安全和性能,又达到了动态语言开发类维护的高效率。

  • GO = C + Python
    • 说明Go语言既有C静态语言程序的运行速度,又能达到Python的动态语言的快速开发。

天然并发:

  • 从语言层面支持并发,实现简单。

  • GoRoutine,轻量级线程,可实现大并发处理,高效利用多核。

管道通信机制:

  • Go语言特有的管道Channel,通过Channel,可以实现不同的GoRoute之间的相互通信。

函数返回多个值。

新的创新内容:

  • 例如切片、延时执行Defer等。

安装

下载地址:https://go.dev/dl/

  • 默认安装路径是/usr/local/go

配置环境变量:

1
$ vim ~/.bash_profile
1
2
3
export GOPATH=/usr/local/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOBIN
1
$ source ~/.bash_profile

验证安装:

1
2
go version
go env

第一个Go程序

一个简单的 Go 程序文件 hello.go

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package main // package main 定义了包名。必须在源文件中非注释的第一行指明这个文件属于哪个包

import (

"fmt"

) /* import "fmt" 告诉 Go 编译器这个程序需要使用 fmt 包(的函数,或其他元素),fmt 包实现了格式化 IO(输入/输出)的函数。 */

func main() { // func main() 是程序开始执行的函数(函数的入口)。main 函数是每一个可执行程序所必须包含的,一般来说都是在启动后第一个执行的函数。

/* 这是hello world的程序 */ // /*...*/ 是注释,在程序执行时将被忽略。单行注释是最常见的注释形式,你可以在任何地方使用以 // 开头的单行注释。多行注释也叫块注释,均已以 /* 开头,并以 */ 结尾,且不可以嵌套使用,多行注释一般用于包的文档描述或注释成块的代码片段。

fmt.Println("Hello,Go World!") // fmt.Println(...) 可以将字符串输出到控制台,并在最后自动增加换行字符 \n。 Print 和 Println 这两个函数也支持使用变量

}

构建该程序:

1
go build hello.go

生成一个名为 hello 的可执行文件,可以运行它。

1
./hello

使用 go install

  • 不仅构建程序,还将结果文件安装到 GOPATH 指定的目录中,以供全局使用。
    • 通常是在 $GOPATH/bin 目录下。
  • 可以在任何地方运行程序。
1
go install hello.go

执行流程分析

如果是对源码编译后,再执行,Go 的执行流程如下图:

img

如果是对源码直接 执行 go run 源码,Go 的执行流程如下图:

img

两种执行流程的方式区别:

  • 如果先编译生成了可执行文件
    • 那么可以将该可执行文件拷贝到没有 go 开发环境的机器上,仍然可以运行。
  • 如果是直接 go run go 源代码
    • 那么如果要在另外一个机器上这么运行,也需要 go 开发环境,否则无法执行。
  • 在编译时,编译器会将程序运行依赖的库文件包含在可执行文件中
    • 所以,可执行文件变大了很多。

开发注意事项

Go 源文件以 go 为扩展名。

Go 应用程序的执行入口是 main() 函数。

Go 语言严格区分大小写。

Go 方法由一条条语句构成,每个语句后不需要分号(Go 语言会在每行后自动加分号)。

Go 编译器是一行行进行编译的

  • 因此一行就写一条语句,不能把多条语句写在同一个,否则报错。

Go 语言定义的变量或者 import 的包如果没有使用到,代码不能编译通过。

大括号都是成对出现的,缺一不可。

通过 go run xxx.go直接运行Go代码。

编译后再运行 go build xxx.go, ./xxx

标识符

命名规则:

  • 由26个英文字母大小写,0-9,_ 组成

  • 数字不可以开头:var num int //这样写是OK的 vat 3num int //这样是错误的

  • Golang中严格区分大小写

  • 标识符不能包含空格

  • 下划线_ 本身在Go中是一个特殊的标识符,称为空标识符

    • 可以代表任何其他的标识符,但是它对应的值会被忽略(比如:忽略某个返回值)
      • 所以仅能被作为占位符使用,不能作为标识符使用
  • 不能以系统保留关键字作为标识符(一共25个),比如break , if 等等

命名注意事项

  • 包名:保持和package的名字和目录是一样的,尽量采取用意义的包名,简短,有意义
    • 不要和标准库有冲突,例如 fmt
  • 变量名、函数名、常量名:采用驼峰法
  • 如果变量名、函数名、常量名首字母大写,则可以被其他包访问:如果首字母小写,则只能在本包中使用

转义字符

常用的转义字符有如下:

  • \t : 表示一个制表符,通常使用它可以排版
  • \n :换行符
  • \\ :一个\
  • \" :一个”
  • \r :一个回车
1
2
3
4
5
6
7
package main

import "fmt" //fmt 包中提供格式化,输出,输入的函数
func main() {
//要求:请使用一句输出语句,达到输入如下图形的效果
fmt.Println("姓名\t 年龄\t 籍贯\t 地址\njohn\t20\t 河北\t 北京")
}

注释

行注释:

  • // 注释内容

块注释(多行注释):

  • /*注释内容*/

变量

声明变量的规则:

  • 以字母或下划线开头,由一个或多个字母、数字、下划线组成

关键字:var

定义变量:

  • 注意Go语言变量一旦定义后续必须要用到,否则会报错

定义变量格式:

  • var 变量名 变量类型
1
2
var a int
var s string

变量赋值:

  • var 变量名 变量类型 = 值
  • 根据值自行判定变量类型
  • 在函数内第一次赋值时可以使用:=替代var来定义赋值变量(在函数外不可以)
    • 编译器也可以自动决定类型
  • 在函数外定义变量是包内变量(不是全局变量)
  • 如果变量已经使用 var 声明过了,再使用 := 声明变量,就产生编译错误
1
2
3
var a int = 5
var b string = "abbc"
var c,d,e,f = 3,5,true,"def" //不需要显示声明类型,自动推断

变量赋值与其他主流语言的区别:

  • 赋值可以进行自动类型推断
  • 在一个赋值语句中可以对多个变量进行同时赋值
1
2
3
4
5
6
7
8
9
10
11
func TestExchange(t *testing.T) {
a := 1
b := 2
//定义中间变量进行变量值的互换
//tmp := a
//a = b
//b = tmp
//在Go中可以这么写
a, b = b, a
t.Log(a, b)
}

程序中+号的使用

  • 当左右两边都是数值型时,则做加法运算

  • 当左右两边有一方为字符串,则做拼接运算

全局变量:

  • 全局变量是定义在函数外部的变量,它在程序整个运行周期内都有效
    • 在函数中可以访问到全局变量。
1
2
3
4
5
6
7
8
9
10
11
12
13
package main

import "fmt"

//定义全局变量num
var num int64 = 10

func testGlobalVar() {
fmt.Printf("num=%d\n", num) //函数中可以访问全局变量num
}
func main() {
testGlobalVar() //num=10
}

常量

关键字const

  • const可以作为各种类型进行使用
1
2
const a,b = 3,4
var c int = int(math.Sqrt(a*a + b*b))

变量赋值与其它主流语言的区别:

  • Go语言可以快速设置连续值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const (
Monday = iota + 1
Tuesday
Wednesday
Thursday
Friday
Saturday
Sunday
)
func TestConstant(t *testing.T) {
t.Log(Thursday, Sunday) //输出结果为:4 7
}
//iota,特殊常量值,是一个系统定义的可以被编译器修改的常量值。
//iota只能被用在常量的赋值中,在每一个const关键字出现时,被重置为0,
//然后每出现一个常量,iota所代表的数值会自动增加1,
//iota可以理解成常量组中常量的计数器,不论该常量的值是什么,只要有一个常量,那么iota 就加1。

数据类型

布尔型

  • 布尔型的值只可以是true或者false

数字类型

  • 整型int、浮点型float32,float64 GO语言支持整型和浮点型数字
    • 并且支持复数,其中位的运算采用补码

字符串类型

  • 字符串就是一串固定长度的字符连接起来的字符序列。
  • Go 的字符串是由单个字节连接起来的。
  • Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。

派生类型

  • 指针类型(Pointer)
  • 数组类型
  • 结构化类型(struct)
  • Channel 类型
  • 函数类型
  • 切片类型
  • 接口类型(interface)
  • Map 类型

零值(初始值)

  • 当一个变量或者新值被创建时,如果没有为其明确指定初始值。
  • Go语言会自动初始化其值为此类型对应的零值,各类型零值如下:
    • bool:false
    • integer:0
    • float:0.0
    • string:""
    • pointer, function, interface, slice, channel, map:nil
  • 对于复合类型,Go语言会自动递归地将每一个元素初始化为其类型对应的零值:
    • 比如:数组,结构体。

与其他主流编程语言的差异

  • Go语言不允许隐式类型转换
  • 别名和原有类型也不能进行隐式类型转换
  • string 是值类型:默认初始化值是空字符串,不是nil
  • 不支持指针运算