一 什么是编程语言
编程语言是用来控制计算机的一系列指令(Instruction),它有固定的格式和词汇(不同编程语言的格式和词汇不一样)。就像我们中国人之间沟通需要汉语,英国人沟通需要英语一样,人与计算机之间进行沟通需要一门语言作为介质,即编程语言。
编程语言的发展经历了机器语言(指令系统)=>汇编语言=>高级语言(C、java、Go等)。
计算机在设计中规定了一组指令(二级制代码),这组指令的集和就是所谓的机器指令系统,用机器指令形式编写的程序称为机器语言。
但由于机器语言的千上万条指令难以记忆,并且维护性和移植性都很差,所以在机器语言的基础上,人们提出了采用字符和十进制数代替二进制代码,于是产生了将机器语言符号化的汇编语言。
虽然汇编语言相较于机器语言简单了很多,但是汇编语言是机器指令的符号化,与机器指令存在着直接的对应关系,无论是学习还是开发,难度依然很大。所以更加接近人类语言,也更容易理解和修改的高级语言就应运而生了,高级语言的一条语法往往可以代替几条、几十条甚至几百条汇编语言的指令。因此,高级语言易学易用,通用性强,应用广泛。
二 编译型语言与解释型语言
计算机是不能理解高级语言的,更不能直接执行高级语言,它只能直接理解机器语言,所以使用任何高级语言编写的程序若想被计算机运行,都必须将其转换成计算机语言,也就是机器码。而这种转换的方式分为编译和解释两种。由此高级语言也分为编译型语言和解释型语言。
编译型语言
使用专门的编译器,针对特定的平台,将高级语言源代码一次性的编译成可被该平台硬件执行的机器码,并包装成该平台所能识别的可执行性程序的格式。
编译型语言写的程序执行之前,需要一个专门的编译过程,把源代码编译成机器语言的文件,如exe格式的文件,以后要再运行时,直接使用编译结果即可,如直接运行exe文件。因为只需编译一次,以后运行时不需要编译,所以编译型语言执行效率高。
1、一次性的编译成平台相关的机器语言文件,运行时脱离开发环境,运行效率高;
2、与特定平台相关,一般无法移植到其他平台;
解释型语言
使用专门的解释器对源程序逐行解释成特定平台的机器码并立即执行。是代码在执行时才被解释器一行行动态翻译和执行,而不是在执行之前就完成翻译。
1.解释型语言每次运行都需要将源代码解释称机器码并执行,执行效率低;
2.只要平台提供相应的解释器,就可以运行源代码,所以可以方便源程序移植;
三 输出hello world
package main //声明文件所在的包,每个go文件必须有所在的包
import "fmt" //引入程序中需要的包,为了使用包下的函数,比如:println
func main() { //main 主函数 程序的入口
fmt.Println("HELLO GO !!!") //在控制台打印输出的字符串
}
//go build test.go 编译代码(Windows下生成可执行程序,Linux下二进制文件)
#go run test.go //通过go run 直接编译为执行文件
HELLO GO !!!
四 程序语法解析
main包和main程序
Go语言以“包”作为管理单位,每个 Go 源文件必须先声明它所属的包,所以我们会看到每个 Go 源文件的开头都是一个 package
声明。
Go语言的包与文件夹是一一对应的。一个Go语言程序必须有且仅有一个 main 包。main 包是Go语言程序的入口包,如果一个程序没有 main 包,那么编译时将会出错,无法生成可执行文件。
import
在包声明之后,是 import 语句,用于导入程序中所依赖的包,导入的包名使用双引号""包围,格式如下:
import "name"
其中 import 是导入包的关键字,name 为所导入包的名字。
注意:导入的包中不能含有代码中没有使用到的包,否则Go编译器会报编译错误
也可以使用一个 import 关键字导入多个包,此时需要用括号( )
将包的名字包围起来,并且每个包名占用一行
import(
"p1"
"p2"
)
五 程序编译执行
Go语言是像C语言一样的编译型的静态语言,所以在运行Go语言程序之前,先要将其编译成二进制的可执行文件。
可以通过Go语言提供的go build
或者go run
命令对Go语言程序进行编译:
(1) go build
命令可以将Go语言程序代码编译成二进制的可执行文件,但是需要我们手动运行该二进制文件;
如果是普通包,当你执行go build之后,它不会产生任何文件。【非main包】
如果是main包,当你执行go build之后,它就会在当前目录下生成一个可执行文件exe
你也可以指定编译输出的文件名。我们可以指定
go build -o xxxx.exe
,默认情况是你的package名(main包),或者是第一个源文件的文件名(main包)
(2)除了使用go build命令外,Go语言还为我们提供了go run命令,go run命令将编译和执行指令合二为一,会在编译之后立即执行Go语言程序,但是不会生成可执行文件。
执行流程分析
上述两种执行流程的方式区别
在编译时,编译器会将程序运行依赖的库文件包含在可执行文件中,所以,可执行文件变大了很多.
如果我们先编译生成了可执行文件,那么我们可将可执行文件拷贝到没有go开发环境的机器上,仍然可以执行.
如果我们是直接go run go源代码,那么如果要在另外一个机器上运行,也需要go开发环境,否则无法执行.
扩展:
编译时指定可执行程序名称:
#go build -o hellogo test.go //-o 指定生成的程序名称
#ls
hellogo test test.go
Go install:
先编译得到一个可执行文件
将可执行文件拷贝到
/gopath/bin
六 Go语言的语法规则
源文件以"go"为扩展名
程序的执行入口是main()函数
严格区分大小写
方法由一条条语句构成,每个语句后不需要分号;(go语言会自动增加分号),这也体现了go语言的简洁性
go编译器是一行一行进行编译的,因此我们就一行一行书写一条语句,不能把多个语句写在同一行
定义的变量或者import的包如果没有使用到,代码不能编译通过
大括号成对出现的缺一不可
七 Go语言的编码风格
注意缩进(vscode需要注意,goland中会自动缩进格式化)
在VScode 中,向后缩进tab键,向前缩进shift +tab
通过命令完成格式化操作:
gofmt -w test.go
一些编码细节:
成对编程 () {} ""
运算符两边加空白
以下的代码是错误的
原因:go的设计者想要开发者有一个统一的代码风格,一个问题尽量只有一个解决方案是最好的
行长约定
一行最长不要超过80个字符,超过的请使用换行展示,尽量保持格式优雅
以上使用拼接字符串展示
八 (跨平台编译)交叉编译
默认我们go build的编译可执行文件都是当前操作系统可执行的文件,go语言支持跨平台编译
Windows 编译Linux可执行文件
如果我想在Windows下编译一个Linux下可执行文件,那需要怎么做呢?只需要在编译时指定目标操作系统的平台和处理器架构即可。
注意:无论你在Windows电脑上使用VsCode编辑器还是Goland编辑器,都要注意你使用的终端类型,因为不同的终端下命令不一样!!!目前的Windows通常默认使用是PowerShell
终端。
如果你的Windows使用的是cmd
,那么按如下方式指定环境变量。
SET CGO_ENABLED=0 // 禁用CGO
SET GOOS=linux // 目标平台是linux
SET GOARCH=amd64 // 目标处理器架构是amd64
如果你的Windows使用的是PowerShell
终端,那么设置环境变量的语法为
$ENV:CGO_ENABLED=0
$ENV:GOOS="linux"
$ENV:GOARCH="amd64"
在你的Windows终端下执行完上述命令后,再执行下面的命令,得到的就是能够在Linux平台运行的可执行文件了。
go build
Windows编译Mac可执行文件
Windows下编译Mac平台64位可执行程序:
cmd
终端下执行:
SET CGO_ENABLED=0
SET GOOS=darwin
SET GOARCH=amd64
go build
PowerShell
终端下执行:
$ENV:CGO_ENABLED=0
$ENV:GOOS="darwin"
$ENV:GOARCH="amd64"
go build
Mac编译Linux可执行文件
Mac电脑编译得到Linux平台64位可执行程序:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build
Mac编译Windows可执行文件
Mac电脑编译得到Windows平台64位可执行程序:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build
Linux编译Mac可执行文件
Linux平台下编译Mac平台64位可执行程序:
CGO_ENABLED=0 GOOS=darwin GOARCH=amd64 go build
Linux编译Windows可执行文件
Linux平台下编译Windows平台64位可执行程序:
CGO_ENABLED=0 GOOS=windows GOARCH=amd64 go build
九 GoPath 开发模式和GoModules开发模式对比
GoPAth模式:
目录结构:
新建 main.go
:
package main
import (
"fmt"
"micro_service/test/old_terst01/calc"
)
//1.一定要将代码新建到GOPATH下的src下面
//2.go env -w GO111MODULE=off
func main() {
fmt.Println("hello!")
calc.Add(3, 4)
}
新建 calc/add.go
外部函数:
package calc
func Add(x, y int) int {
return x + y
}
编译运行:
main.go:5:2: package micro_service/test/old_terst01/calc is not in GOROOT (C:\go\src\micro_service\test\old_terst01\calc)
报错原因是:go先查找gopath/src这个目录下包含是否有,然后在goroot/src目录下查找
解决这个问题需要把GO111MODULE=设置为GO111MODULE=off go env -w GO111MODULE=off
GoModules 模式:
在项目目录中新建一个 go.mod 文件:
go 1.15
module micro_service/test/old_terst01
编译运行: