简介
-
GO 从C语言中继承了很多 理念,包括表达式语法,控制结构,基础数据类型,调用参数传值,指针等等,也保留了和C语言一样的编译执行方式及弱化的指针。
-
引入 包 的概念,用于组织程序结构,Go语言的一个文件都要归属于一个包,而不能单独存在。
-
垃圾回收机制,内存自动回收,不需开发人员管理
-
天然并发
(1)从语言层面支持并发,实现简单。
(2) goroutine,轻量级线程,可实现大并发处理,高效利用多核。
(3)基于CPS并发模型(Communicating Sequential Processes )实现。 -
吸收了管道通信机制,形成 Go 语言特有的管道 channel ,通过管道,可以实现不同的 goroute 之间的相互通信。
-
函数可以返回多个值。
Go 的 hello world
下面书写一个 go 版本的 hello world
package main
import "fmt"
func main(){
fmt.Println("hello ,world")
}
- 编译
go build hello.go
:
参数说明:
-o 指定编译后文件的名称
# 通过 build 命令将文件转化为二进制
# 指向完下面的命令后,会生成一个 hello 的一个文件
$ go build hello.go
- 运行
$ ls
hello hello.go
$ hello
hello, world
说明
go 为了方便测试,也可以通过 go run
直接进行运行,类似于执行一个脚本文件,但是不能用于生产环境。
这个过程中也是会编译成二进制源码的,因此速度相对来说较慢。
如果此时 demo 里面有错误,编译的时候会进行提示,例如如下代码:
package main
// 引入 fmt 就表示可以使用 fmt 包的函数
import "fmt"
func main(){
// 表示主函数(程序的入口)
fmt.Println("hello, world")
fmt.Pri232("hello, world")
}
编译:
$ go build hello.go
# command-line-arguments
./hello.go:7:2: undefined: fmt.Pri232
Golang 的执行流程分析
- 如果是对源码编译后,再执行,Go 的执行流程如下图:
![XOadn1](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/XOadn1.png)
![VqbfKB](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/VqbfKB.png)
-
如果我们先编译生成了可执行文件,那么我们可以将该可执行文件拷贝到没有go开发环境的机器
上,仍然可以运行 -
如果我们是直接
go run
执行 go 源代码,那么如果要在另外-一个机器上这么运行,也需要go开发环境,
否则无法执行。 -
在编译时,编译器会将程序运行依赖的库文件包含在可执行文件中,所以,可执行文件变大了很多。
开发注意事项
杂项
- Go源文件以"go"为扩展名。
- Go应用程序的执行入口是main()函数。
- Go语言严格区分大小写。
- Go方法由一条条语句构成,每个语句后不需要分号(Go语言会在每行后自动加分号),这也体现出Golang的简洁性。
- Go编译器是一行行进行编译的,因此我们一行就写一条语句,不能把多条语句写在同一个,否则报错
- go语言定义的变量或者 import 的包如果没有使用到,代码不能编译通过。
![1X71WO](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/1X71WO.png)
- 大括号都是成对出现的,缺一不可。
- Go 当中,一个包只能有一个 main 函数,如果有同名的话,会报错。
解决方案:新建一个文件夹
![FE71Rj](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/FE71Rj.png)
- vscode 安装 go 插件失败。
解决办法:
# 打开 GO111MODULE, 并切换为国内源
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.cn,direct
重新打开 vscode,选择一键安装。
更多可以参考此篇文章:
- 如果我们希望自己的 GO 项目在
GOPATH/src
外面进行运行的话,需要基于 Go Module 来进行创建:
- 例如我们想要在
~/Coding/tour
这个目录下创建一个工程
~/Coding/go ⌚ 15:00:55
$ mkdir tour
~/Coding/go ⌚ 15:01:02
$ cd tour
~/Coding/go/tour ⌚ 15:01:10
$ go mod init flysnow.org/tour
go: creating new go.mod: module flysnow.org/tour
~/Coding/go/tour ⌚ 15:01:20
$ ls
go.mod
~/Coding/go/tour ⌚ 15:01:22
$ cat go.mod
module flysnow.org/tour
go 1.16
这个时候我们打开 VSCODE,写入如下内容:
![fXdBaK](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/fXdBaK.png)
package main
import (
"fmt"
"flysnow.org/tour/model"
)
func main() {
fmt.Println("Hello World")
fmt.Printf("model.Hero: %v\n", model.Hero)
}
基础内容
1. Go 转义字符
字符 | 说明 |
---|---|
\t | 一个制表位,实现对其功能 |
\n | 换行符 |
\\ | 一个 \ |
\" | 一个“ |
\r | 一个回车,fmt.Println(“天龙八部雪山飞狐/r张飞”) |
2. 注释
行注释
// 大家好,我是注释内容
块注释
/*
大家好,我是块注释
*/
3.代码格式规范
格式规范
需要正确的进行代码的缩进和对其,可以通过命令行的方式来进行格式的调整:
gofmt -w main.go
-w
参数:该参数用来将格式化完成的代码写回到 main.go 这个文件中。如果没有-w
参数的话,只能打印到控制台上。
代码风格
函数的括号只能以一种方式来进行,否则编译器报错:
// 正确的形式
func main() {
// 演示转义字符的使用
fmt.Println("tom\rjack")
fmt.Println("C:\\Users\\Administrator\\Desktop")
fmt.Println("tom 说:\"i love you\"")
}
Go 语言不允许使用如下的方式来书写:
![8fwVHt](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/8fwVHt.png)
4. 文档内容
-
官方的接口文档位于:接口文档
-
官方的简易教程文档:A Tour of Go
-
Mac 系统中查看 Go 的源码,位于:
/opt/homebrew/Cellar/go/1.16.5/libexec/src # 里面是一堆包
![](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/df0qsn.png)
1. 单个变量的声明方式
- 声明变量并指定类型
func main() {
// 定义变量, 声明变量后, 若不赋值, 使用默认值,int 的默认值为 0
var i int
// 给 i 赋值
i = 10
fmt.Println("i=", i)
}
打印输出:
i= 10
- 根据值自行判定变量类型
func main() {
var num = 10.11
fmt.Println("num = ", num);
}
打印输出:
num = 10.11
- 省略
var
进行声明。如果声明时就直接赋值,可以省略数据类型。
注意: :=
左侧的变量至少一个是已经声明过的,否则会导致编译错误。
func main() {
name := "tom"
// 下面的方式等价于 var name string; name ="tom"
fmt.Println("name=",name)
}
2. 一次性声明多个变量
- 通过
var
一次性声明多个变量,并使用默认值
func main() {
var n1, n2, n3 int
fmt.Println("n1=",n1,"n2=",n2,"n3=",n3)
}
打印输出:
n1= 0 n2= 0 n3= 0
- 根据值进行类型推到
func main() {
n1, name, n3 := 100, "tom~", 888
fmt.Println("n1=", n1, "name=", name, "n3=", n3)
}
打印输出:
n1= 100 n2 0 name= tom~
- 通过括号进行多个声明:
var (
n3 = 300
n4 = 900
name2 = "marry"
)
func main() {
// 输出全局变量
fmt.Println("n1=", n1, "n2", n2, "name=", name)
}
打印输出:
n3= 888 n4 0 name2= marry
总结:因为简洁和灵活的特点,简短变量声明被广泛用于大部分的局部变量的声明和初始化。var
形式的声明语句往往是用于需要显式指定变量类型地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方。
3. 注意事项
- 变量可以在作用域内进行改变,但是不能改变其变量类型
![btUerI](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/btUerI.png)
func main() {
var i int = 10
i = 30
i = 50
// i = 1.2 // 不能改变数据类型
fmt.Println("i=", i)
// 变量在同一个作用域内(在一个函数或者在代码块里)内不能重名
var i int = 59
}
![KS3vKg](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/KS3vKg.png)
4. 变量中 + 的使用
在 Go 当中,+ 和 Python 中的用法类似:
- 如果两边都是数值类型的话,做加法运算。
- 当左右两边都是字符串的话,则做字符串拼接。
package main
import "fmt"
func main() {
var i = 1
var j = 2
var r = i + j
fmt.Println("r=", r)
var str1 = "hello"
var str2 = "world"
var res = str1 + str2
fmt.Println("res=", res)
}
GO 语言的数据类型
![Wt1CFZ](https://gitee.com/xiangzhaocheng/img_upload/raw/master/uPic/Wt1CFZ.png)
一位表示 8 个字节
类型 | 有无符号 | 占用存储空间 | 表示范围 |
---|---|---|---|
int8 | 有 | 1字节 | -128~127 |
int16 | 有 | 2字节 | − 2 15 -2^{15} −215 ~ 2 15 − 1 2^{15}-1 215−1 |
Int32 | 有 | 4字节 | − 2 31 -2^{31} −231 ~ 2 31 − 1 ~2^{31} - 1 231−1 |
int64 | 有 | 8字节 | − 2 63 -2^{63 |