欢迎访问我的博客,你的支持,是我最大的动力!

Go语言学习笔记(1)-基础/数据类型/流程控制

Linux 小马奔腾 1767℃ 评论
目录:
[显示]

Go语言开发环境部署

官网:https://golang.org/
下载:https://golang.org/dl/
文件:https://dl.google.com/go/go1.11.2.windows-amd64.msi  111MB
文件:https://dl.google.com/go/go1.11.2.linux-amd64.tar.gz  121MB

环境变量
$GOROOT,Go语言安装位置,一个绝对路径
$GOPATH,Go语言工作目录,可以设置多个,go get 下载的库默认安装到第一个工作目录

Linux系统
curl -Lo golang.tar.gz https://dl.google.com/go/go1.11.2.linux-amd64.tar.gz
tar zxf golang.tar.gz -C /opt
mkdir -p /home/golang/{go,other}
在/etc/profile尾部添加
export GOROOT=/opt/go
export GOPATH=/home/golang/go:/home/golang/other  #多个工作目录用:分隔
export PATH=$PATH:$GOROOT/bin:${GOPATH//://bin:}/bin   #注意${GOPATH//://bin:}在存在多个工作目录时使用,表示每个工作目录
## ${GOPATH//://bin:} -> 前面的红色/是替换分隔符  结果是将/:替换为/bin:
source /etc/profile #让环境变量生效

Windows系统
仅需设置环境变量,具体位置没有要求
如:GOROOT C:\Go\
添加PATH 添加 C:\Go\bin 或 %%GOROOT\bin
如:GOPATH E:\golang;E:\go   #多个工作目录使用;分隔

Go命令
# 查看帮助
go help
# 查看详细帮助
go help [command]
# 编译源代码包和依赖
go build  #不带参数默认编译当前目录的源码
go build -a  #强制重新编译所有相关的Go源代码包,包括标准库中的包,适用于对底层代码做过修改后的编译
go build -n  #显示实际编译过程中要执行的命令,实际不编译
go build -p 3 #构建时指定并行运行的程序数量,默认是可用的CPU数量
go build -race #检查数据竞争关系,用于并发编程,仅支持amd64架构
# 编译并安装指定的包与依赖
go install
# 编译并运行Go程序
go run main.go
# 删除对象文件
go clean
go clean -r #清理导入代码包中的构建缓存
# 显示Go包或程序实体的文档
go doc
# 打印Go环境变量
go env
# 格式化代码 (编译时,会自动格式化所有源代码)
go fmt
gofmt -r "原始内容 -> 替换内容" -w *.go  #批量替换 -w 写入到文件
# 下载并安装指定包与依赖
go get
go get -d #只下载不执行安装动作
go get -fix #下载后先执行代码兼容性修复动作,再进行编译和安装
go get -insecure #允许使用http协议下载代码包
go get -u #更新已有代码包与依赖包(默认不会下载本地已经存在的代码包)
# 打印指定源码包的信息
go list
# 检查源码包中可能出现的错误
go vet
# 使用go tool工具
go tool

Go文档服务
godoc -http=:8080  #golang.org的本地站点

GOROOT下的misc目录存放的是辅助工具和说明

GOPATH下通常有三个目录:bin,pkg,src(存放源码,目录结构:/组织/项目/源码 如/github.com/test/*.go)

交叉编译
go env显示环境变量,设置$GOOS和$GOARCH变量就可以指定构建相应的Go语言程序
$GOOS,目标操作系统,如linux,windows,android等10种操作系统
$GOARCH,架构,如amd64,arm,arm64等9种架构
构建linux amd64的程序
GOOS=linux GOARCH=amd64 go build
构建windows amd64的程序
GOOS=windows GOARCH=amd64 go build

开发工具
1、Visual Studio Code
2、Atom
3、VIM-Go 详见:CentOS7系统基于Vim8搭建Go语言开发环境
4、Gogland,Jetbrains公司出品,支持IntalliJ插件,商业软件,需要jre环境
5、LiteIDE,下载:https://github.com/visualfc/liteide/releases 推荐,绿色软件
6、Cloud IDE
6.1、Eclipse Che,docker run eclipse/che start
6.2、Cloud9 IDE,基于Node.js,docker,zuolan/cloud9-ide
6.3、Wide

Go基础

程序入口是main包的main函数
import导入的包必须要使用
若一个变量没有使用,编译时会报错,可以使用 _=a 来使用变量,编译器会认为变量a使用了
行结束不需要分号;,多行写到一行,使用分号分隔语句

程序元素

Go语言程序包含5种符号:标识符 identifier、关键字keyword、运算符operator、分隔符delimiter、字面量literal

标识符
以a~zA~Z或_开头,不能出现@ $ % 等符号
数据类型:bool byte uint16 float32 float64 int int16 uint32 int32 int64 uint64 string uint uint8 uintptr
内建函数名:append cap close complex copy delete imag len make new panic print println real recover
其他:iota nil _

关键字
共有25个关键字
包导入与声明:import package
程序实体声明与定义:var type func interface map struct chan const
流程控制:if continue for return go case goto switch select else break default defer fallthrough range

字面量
表示值,构造struct、array、slice、map的值等

分隔符
括号、小数点、逗号、分号、冒号、省略号
go语言不需要以分号;结尾

运算符
运行符优先级:一元运算符 > 二元运算符 同级别按从左到右顺序
注:++和--是语句,不是表达式,没有运算符优先级之说;Go语言不支持运算符重载
注:* 取值操作,获取某地址代表的值; &取址操作获取某变量的内存地址

注释
// 这是注释内容
/* 这是注释内容 */
/* 这是
多行
注释 */

基本概念
常量

使用关键字 const ,编译期间就已知(可涉及计算过程,可使用内置函数,但编译期间要能确定具体值)且执行中不会改变的值,可以为数值、布尔值、字符串等类型
格式:const identifier [type] = value  其中type可以省略,go编译器会智能判断值类型
如:
const Pi = 3.14159
const Return = true
若是超长小数位,默认会自动缩减为float64
常量定义中支持反斜杠\跨行  #实际测试中发现并不支持

数字表示
十六进制:前缀 0x 或 0X
八进制:前缀 0
整数:可以有一个后缀 U u (unsigned) 或 L l (long)  #实际测试中发现并不支持

转义字符
使用\转义,如
\\ -> \
\' -> '
\" -> "
\? -> ?
\b -> 退格
\f -> 换页
\n -> 换行
\r -> 回车
\t \v -> 水平制表符 垂直制表符

赋值
a := 2
b = a
b *= a
const 人数, 费用, 班级 = 40, 200, "一班"  //并行赋值

枚举
iota起始值为0,然后递增;每个独立的const中,iota会重新赋值;iota可参与计算
未指定的值默认为上面那个常量值;若在同一行,iota值相同,见下面的示例

变量

格式:var identifier type

// 同一类型的多个变量可声明在同一行
var a,b,c int
// 声明可一并进行赋值
var a,b,c int = 1,2,3
var a,b,c = "string",1,true
a := 1  //注:只能用在函数体内,不能用于全局变量声明和赋值
// 多个变量声明
var (
a,b int
c bool
str string
)
// 交换变量值
a,b = b,a

变量声明要点:
同一代码块内不能多次声明同一个变量
函数内可使用全局定义的变量,并赋予一个新的值,但类型必须与声明时的一致
函数体属于独立代码块,可再次声明与全局变量同名但类型不相同的变量
全局定义不限制位置,通常统一放在函数代码前面
变量声明但没有赋值时,默认为各类型的零值
// int为0,float为0.0,bool为false,string为空字符串,指针为nil 若变量未指定类型,默认为int型
变量命名一般遵循驼峰命名法,常量一般全部大写
局部变量定义后必须使用,全局变量定义后可不使用

init 函数

init 函数,每一个源文件有且只能有一个 init 函数,优先级比 main 函数高,init 函数在包初始化后自动执行,存在多个 init 函数时,初始化过程会根据包依赖关系按顺序单线程执行

基础数据类型

数据类型主要为提高内存利用效率,确定程序实体在内存中的空间占用和存储方式
Go支持使用八进制、十进制、十六进制及科学计数法表示数字;math库中定义有各数字类型的取值范围
如:Int8范围 math.MinInt8 <-> math.MaxInt8  (-128,127)

整型

int8 int16 int32 int64,uint8 uint16 uint32 uint64,uintptr (多用于底层编程) 大小分别对应8、16、32、64b
注:也可直接使用int和uint类型,但会根据平台对应int32 int64 / uint32 uint64
int32 别名 runeuint8 别名 byte

两种不同类型的整型,不能直接比较、不能直接运算,但各种类型的整型变量都可以直接与字面量比较,若要运行需要强制转换类型

浮点型

float32 float64
float32精确到小数点后7位;float64精确到小数点后15位
注意,没有float型,建议只使用float64 (math库中所有数学运算函数都接收float64类型参数)

浮点型需要注意精度问题

复数
形如 a+bi 其中ab均为浮点型
complex64 32位实数和虚数
complex128 64位实数和虚数
real() 获取实部;imag() 获取虚部
更多:math/cmplx 标准库

var v1 complex64
v1 = 3.2 + 12i
v2 := 3.2 + 12i
v3 := complex(3.2, 12)

字符串

字符串是不可改变的UTF-8字符序列
因为是UTF-8编码,所以占用内存为1~4字节,len() 返回的是字节数,不是字符数

非解释字符串(忽略转义符\) 使用反引号`括起来,支持换行
反单引号可以跨行,且引号内的所有内容都会输出,包括转义字符和空格缩进等
双引号不能换行,会解析转义字符
注意,单引号不能括字符串

字符串截取操作 str1[0:4]
字符串连接操作 str1 + str2
字符串比较操作 str1 < str2
字符串遍历操作 range str

字符串修改
不能使用 str[i] 方式修改字符串,若要修改,可将字符串内容复制到可写变量中,再修改,一般使用 []byte 或 [rune] 类型
[]byte 对字符中字节进行修改 []byte(str)
[]rune 对字符进行修改

注:获取字符串中某字节地址的行为是非法的,如 &str[i]

strings 库

1、包含判断
判断某个字符串中是否有某个子字符串
strings.HasPrefix(str,char string) bool,判断字符串str中前缀是否包含char
strings.HasSuffix(str,char string) bool,判断字符串str中后缀是否包含char
strings.Contains(str,char string) bool,判断字符串str中是否包含子串char
strings.ContainsAny(str,char string) bool,判断字符串str中是否包含子串char
注:Contains和ContainsAny有区别,ContainsAny不太好理解

2、索引
获取指定字符/串在字符串中出现的位置,若不存在则返回-1
strings.Index(str,char string) int,返回char在str中第一次出现的位置,未出现返回-1
strings.LastIndex(str,char string) int,返回char在str中最后一次出现的位置,未出现返回-1

strings.IndexRune(str string,ch int) int  //注意,第二个参数是int,即用单引号,不能用双引号
# strings.IndexRune("我是中国人",'中') // 6
# fmt.Println('中') //20013
# fmt.Println(reflect.TypeOf('中')) // int32
注:单个汉字是int32型

3、替换
strings.Replace(str,old,new string,n int) string  其中n为替换的次数,0不替换,-1全部替换
# strings.Replace("我是中国人","中国","新",1) //我是新人

4、统计
出现频率
统计指定字符串出现的频率
strings.Count(str,substr string) int 其中str是原字符串,substr是要统计的子字符串
字符数量
len([]rune("我是中国人")) // 5
import "unicode/utf8"
utf8.RuneCountInString("我是中国人") // 5

5、大小写转换
strings.ToLower( string ) string 将字符串中Unicode字符转为小写
strings.ToUpper( string ) string 将字符串中Unicode字符转为大写

6、修剪
去掉一些不需要的字符
strings.Trim( str , s string ) string 修剪字符串str开头或结尾的字符,不匹配中间的字符,第二个参数s在转换时会转换成rune再处理,即分成单个的字来处理
strings.TrimLeft( str,s string ) string 修剪字符串str左侧的字符
strings.TrimSpace( str string ) string 修剪字符串str开头或结尾的空格

7、分割
strings.Split 返回切片
strings.Split( str,s string ) slice
# fmt.Printf("%q\n", strings.Split("thanks", ""))   // ["t" "h" "a" "n" "k" "s"]

8、插入字符
strings.Join将元素类型为string的slice使用分隔符号拼接成字符串
strings.Fields 函数把字符串转换为字符串切片
strings.Join 向字符串切片插入指定的字符,此外,也可以使用字节缓冲 bytes.Buffer 连接字符串

strconv 库

字符串与其他类型的转换
数字 -> 字符串,strconv.Itoa( str string)( s string,err error) 将十进制转换为字符串
数字 -> 字符串,strconv.FormatFloat( f float64, fmt byte, prec int, bitSize int ) string , 将float64转换为字符串
# 其中fmt表示格式,值为b,e,f,g;prce 表示精度;bizSize值为32,64表示float32,float64
字符串 -> 数字,strconv.Atois ( s string ) ( i int, err error ) ,将字符串转换为int型
字符串 -> 数字,strconv.ParseFloat( s string, bitSize int )( f float64,err error ),将字符串转换为float64型
strconv.IntSize 操作系统位数,如64

字符串格式化

布尔型

布尔值只有 true 或 false ,不支持使用 0 1 表示真假
布尔类型无法被其他类型赋值,也不支持类型转换

布尔型支持的运行类型
! && ||
&&和||遵循短路径原则,即&&左边值为false时,或||左边为true时,右边表达式将不会执行,所以可以将复制运算放到右侧执行,以减少不必要的运算

基本数据类型的扩展
强制类型转换

将一种类型转换为另一种类型
数据转换时,需要注意数据长度被截取而发生的数据精度损失和值溢出
type_name(expression)
float32("3.12")

自定义类型

type stu struct {
Name string // 可以使用stu.Name访问,可以使用setName和getName
age int //可以使用setAge和getAge方法
}

类型别名

type 字符串 string
var str 字符串
注意:类型别名与原类型是两种类型,不能直接操作,需要进行类型转换

指针

指针是一个变量,其值是另一个变量的地址;所有指针的实际数据类型都是相同的,表示内存地址的十六进制数
内存位置,可以使用&运算符访问
声明一个指针: var name *type
使用指针的步骤:
1、定义一个指针变量
2、将一个变量的地址赋值给一个指针
3、访问指针变量中可用地址的值

Go不支持指针运算

1、nil 指针
刚声明的指针默认值为 nil
var ptr *int
对一个空指针的反向引用是非法的,会会程序崩溃,如
var p *int = nil ; *p = 10

2、指针的指针
定义一个指针的指针:var ptr **int

3、指针数组
数组中有多个值,指向数组的指针也会有多个值
数据:a:=[3]int{1,2,3}
指针数组:var ptr [3]*int
获取值:*ptr[i]

4、传递给函数
传递指针到函数,只需将函数的参数声明为指针类型

Go语言数据类型:基础类型、复合类型、引用类型、接口类型
基础类型:数字、字符串、布尔型

流程控制

Go语言没有 do - while 语句,但 for 被强化;switch 支持类型判断和初始化子语句
defer 捕获异常和资源回收
select 多分支选择,配合通道使用
go 用于异步启动 goroutine

条件语句

代码块:{ 一对大括号中的代码 } 每个代码块内部拥有自己的局部变量

if 判断

if 条件判断语句 { 要执行的代码块 }
# if true { fmt.Println("OK") }

if-else 判断

if condition { ... } else { ... }

else-if 判断

解决多重判断的问题,遇到匹配项后,直接返回,不再判断后续条件,最后的else可以没有

初始化子语句

if 语句可以有一个子语句,初始化局部变量,如 if a:=91; a < 90 { ... }
注,子语句只能有一个表达式;a的值是在 if 代代码块中定义的,不能在代码块外调用
a:=10;b:=20;a>10 { ... }  //这是错误
a,b:=10,20;a>10 { ... }    //这是正确

选择语句

if 常用于二元判断;选择语句一般用于多元判断

switch 语句

若已遇到符合的 case 那么后面的 case 都不会被执行,若没有遇到的 case 则执行 default case
fallthrouth 可以将当前 case 控制权交给下一个 case 语句判断

1、表达式 switch

表达式可以在 switch 层,也可以在 case 层;表达式可以有多个;fallthrough 可以将该 case 的控制权交由下一个 case

2、类型 switch

针对变量类型判断执行某个 case
类型 switch 初始化子语句中需要判断的变量必须是具有接口类型的变量

switch 初始化语句

switch 关键字后可以有一个初始化语句
:初始化语句的分号不能省略

switch marks:=90; marks { case ...
switch marks:=90; { case ...

select 语句

select 也是一种选择语句,用于配合通道 channel 的读写操作,用于多个 channel 的并发读写操作
switch 是按顺序从上到下依次执行,select 是随机选择一个 case 来判断,直到匹配其中的一个 case

channel 的读写操作是阻塞的,使用select 可以避免单个 channel 的阻塞
select 可以使用 default 代码块,避免所有 channel 同时阻塞

循环语句

循环语句使用 for ,没有while 关键字

for 的子语句

for 初始化子语句; 条件子语句; 后置子语句 { ... } 其中条件子语句是必需的,条件子语句返回布尔型值
for ; i<5 ; i++ { ... } //若第一项不存在,可省略,只保留一个分号;
i++可以认为在代码块最后执行,或者说在进行条件子句判断前执行

range 子语句

轮询数组、切片、字符串、字典、通道中的元素
对空字典、空切片、空数组、空字符串等情况,for 会直接结束,不会循环

defer 延迟语句

defer 只能出现在函数内部,defer 后面的表达式必须是外部函数的调用
1、只有当 defer 语句全部执行, defer 所在函数才算真正结束执行
2、当函数中有 defer 语句时,要等待所有 defer  语句执行完毕,才会执行 return 语句

defer 常用于回收资源、清理收尾工作
defer 相当于一个栈,即后进先出,最后面的 defer 语句最先执行

标签

标签可以给 for 、switch、select 等流程控制代码块打上标签,配合标签标识符可以方便跳转到某一个地方继续执行,可以提高编程效率
标签名称区分大小写,建议使用大写字母
标签可以标记任何语句,并不限定于流程控制语句,未使用的标签会引发错误

break

break 不带标签会跳出当前层次代码块
break 带标签可以跳出当前代码块甚至其父代码块

continue

continue 跳转到指定代码块位置继续执行,continue 仅用于 for 循环

goto

goto 无条件跳转到相同函数中带标签语句处
goto 只能在同一个函数中跳转

 

转载请注明:轻风博客 » Go语言学习笔记(1)-基础/数据类型/流程控制

喜欢 (0)or分享 (0)