go 学习 (二):基本语法
一、数据类型
- 布尔型:布尔型的值只可以是常量 true 或者 false。eg:var bo bool = true。布尔型无法参与数值运算,也无法与其他类型进行转换
- 数字类型:整型 int 、浮点型 float32、float64。
- 字符串类型:字符串就是一串固定长度的字符连接起来的字符序列。Go 的字符串是由单个字节连接起来的。Go 语言的字符串的字节使用 UTF-8 编码标识 Unicode 文本。
派生类型:
- 指针类型(Pointer)
- 数组类型
- 结构化类型(struct)
- Channel 类型
- 函数类型
- 切片类型
- 接口类型(interface)
- Map 类型
a、数字类型
整数
无符号整数类型:
uint8:无符号 8 位整型 (0 到 255)
- uint16:无符号 16 位整型 (0 到 65535)
- uint32:无符号 32 位整型 (0 到 4294967295)
- uint64:无符号 64 位整型 (0 到 18446744073709551615)
- 有符号整数类型:
- int8:有符号 8 位整型 (-128 到 127)
- int16:有符号 16 位整型 (-32768 到 32767)
- int32:有符号 32 位整型 (-2147483648 到 2147483647)
- int64:有符号 64 位整型 (-9223372036854775808 到 9223372036854775807)
注:
int 表示有符号整数,uint 表示无符号整数;int 和 uint 所能表示的整数大小根据计算机硬件和编译器不同,会在 32bit 或 64bit 之间变化。
Unicode 字符的 rune 类型和 int32 类型是等价的,byte 和 uint8 也是等价类型。
另外还有 无符号的整数类型 uintptr,它没有指定具体的 bit 大小但足以容纳指针。uintptr 类型只有在底层编程时才需要,特别是Go语言和C语言函数库或操作系统接口相交互的地方。
浮点数
- float32:常量 math.MaxFloat32 表示 float32 能取到的最大数值,大约是 3.4e38;最小值为 1.4e-45 ;可提供大约 6 个十进制数的精度。
- float64:常量 math.MaxFloat64 表示 float64 能取到的最大数值,大约是 1.8e308;最小值为 4.9e-324 ;可提供大约 15 个十进制数的精度,应优先使用 float64 类型
复数
- complex64(32 位实数和虚数)
- complex128(64 位实数和虚数)
复数使用 re+imi 来表示,其中 re 代表实数部分,im 代表虚数部分,i 代表根号负 1;eg:-1+0i
内建的 real 和 imag 函数分别返回复数的实部和虚部
b、字符串类型
- 转义字符:
- \n:换行符
- \r:回车符
- \t:tab 键
- \u 或 \U:Unicode 字符
- \\:反斜杠自身
- 索引访问:
- 字符串 str 的第 1 个字节:str[0]
- 第 i 个字节:str[i - 1]
- 最后 1 个字节:str[len(str)-1]
注意:获取字符串中某个字节的地址属于非法行为,例如 &str[i]。
- 字符串拼接符:”+“ 直接连接字符串
- 定义多行字符串: “ `` ”
- len(): 表示字符串的 ASCII 字符个数或字节长度 ,返回一个 int 整型
- 字符串遍历:
- ASCII 字符串遍历直接使用下标。
- Unicode 字符串遍历用 for range。
- 字符串截取使用类似python的切片存在,利用索引截取:s = str[start:end]
- 格式化操作符:
- %v 按值的本来值输出
- %+v 在 %v 基础上,对结构体字段名和值进行展开
- %#v 输出 Go 语言语法格式的值
- %T 输出 Go 语言语法格式的类型和值
- %% 输出 % 本体
- %b 整型以二进制方式显示
- %o 整型以八进制方式显示
%d 整型以十进制方式显示
%x 整型以十六进制方式显示
%X 整型以十六进制、字母大写方式显示
%U Unicode 字符
%f 浮点数
%p 指针,十六进制方式显示
c、字符类型
- uint8 类型,或者叫 byte 型,代表了 ASCII 码的一个字符。byte 类型是 uint8 的别名
- rune 类型,代表一个 UTF-8 字符,当需要处理中文、日文或者其他复合字符时,则需要用到 rune 类型。rune 类型等价于 int32 类型。
- Unicode包的内置函数:
- 判断是否为字母:unicode.IsLetter(ch)
- 判断是否为数字:unicode.IsDigit(ch)
- 判断是否为空白符号:unicode.IsSpace(ch)
二、变量 & 常量
变量
// 第一种声明变量方式: 指定变量类型,进行初始化或使用默认值
var boolean1 bool // 声明单个变量
var num1, num2 int // 声明多个相同类型的变量
// 第二种声明变量方式:
var num3 int =
var num3 = // 系统根据 值 自行判定变量类型 // 第三种声明变量方式: 省略 var,若 := 左侧未声明新的变量,则产生编译错误
str1 := "u_u"
str1, str2, str3 := "-_-", "^_^", "8_8"
注:
- 变量命名遵循小驼峰命名法
- := 只能用于函数内部定义变量,且使用 := 时必须确保此变量在此之前从未声明使用过,var 一般用于定义全局变量
- _ 是一个特殊的变量名,任何赋予它的值都会被丢弃
- 声明的局部变量必须在其代码块中使用,全局变量可不必
- reflect.TypeOf(variable):可获取变量 variable 的类型
常量
// 定义语法: const name [type] = value const pi = 3.14159 // const 定义常量时,必须要有初始值 const Pi float32 = 3.1415926 const (
e = 2.7182818
pi = 3.1415926
) // 常量使用关键字 const 定义,用于存储不会改变的数据,常量是在编译时被创建的,即使定义在函数内部也是如此,并且只能是布尔型、数字型(整数型、浮点型和复数)和字符串型。
// 常量的值必须是能够在编译时就能够确定的,可以在其赋值表达式中涉及计算过程,但是所有用于计算的值必须在编译期间就能获得。
iota 枚举
// iota关键字通常用来声明enum的时候用,它默认开始值是0,每调用一次+1. const (
first = iota
second
third
fourth = "power"
fifth
sixth =
seventh
eighth = iota
ninth
tenth
) // [Output]: 0 1 2 power power 22 22 7 8 9
三、运算符
算术运算符 | 描述 |
---|---|
+ | 相加 |
- | 相减 |
* | 相乘 |
/ | 相除 |
% | 求余 |
++ | 自增 |
-- | 自减 |
关系运算符 | 描述 |
---|---|
== | 检查两个值是否相等,如果相等返回 True 否则返回 False。 |
!= | 检查两个值是否不相等,如果不相等返回 True 否则返回 False。 |
> | 检查左边值是否大于右边值,如果是返回 True 否则返回 False。 |
< | 检查左边值是否小于右边值,如果是返回 True 否则返回 False。 |
>= | 检查左边值是否大于等于右边值,如果是返回 True 否则返回 False。 |
<= | 检查左边值是否小于等于右边值,如果是返回 True 否则返回 False。 |
逻辑运算符 | 描述 |
---|---|
&& | 逻辑 AND 运算符。 如果两边的操作数都是 True,则条件 True,否则为 False。 |
|| | 逻辑 OR 运算符。 如果两边的操作数有一个 True,则条件 True,否则为 False。 |
! | 逻辑 NOT 运算符。 如果条件为 True,则逻辑 NOT 条件 False,否则为 True。 |
赋值运算符 | 描述 |
---|---|
= | 简单的赋值运算符,将一个表达式的值赋给一个左值 |
+= | 相加后再赋值 |
-= | 相减后再赋值 |
*= | 相乘后再赋值 |
/= | 相除后再赋值 |
%= | 求余后再赋值 |
<<= | 左移后赋值 |
>>= | 右移后赋值 |
&= | 按位与后赋值 |
^= | 按位异或后赋值 |
|= | 按位或后赋值 |
其他运算符 | 描述 |
---|---|
& | 返回变量存储地址 |
* | 指针变量。 |
关键字
break | default | func | interface | select |
case | defer | go | map | struct |
chan | else | goto | package | switch |
const | fallthrough | if | range | type |
continue | for | import | return | var |
标识符
append | bool | byte | cap | close | complex | complex64 | complex128 | uint16 |
copy | false | float32 | float64 | imag | int | int8 | int16 | uint32 |
int32 | int64 | iota | len | make | new | nil | panic | uint64 |
println | real | recover | string | true | uint | uint8 | uintptr |
四、分支循环语句
分支语句
// if 语句
if condition { // condition 为 布尔类型
// do something
} // if-else 语句
if condition { // if 为真即成立,执行 if代码块;否则执行 else代码块
// do something
} else {
// do something
} // if-else if-else 语句
if condition1 {
// do something
} else if condition2 {
// do something else
} else {
// catch-all or default
} // if 的特殊姿势
if err := Connect(); err != nil { // Connect() 为带有返回的函数,此条件先获取函数的返回值,再根据这个返回值进行判断
fmt.Println(err)
return
} // switch 语句
var a = "hello"
switch a {
case "hello":
fmt.Println()
case "world":
fmt.Println()
default:
fmt.Println()
} // 一分支多值 var a = "mum"
switch a {
case "mum", "daddy":
fmt.Println("family")
} // 分支表达式
var r int =
switch {
case r > && r < :
fmt.Println(r)
}
注意:
每个 switch 只能有一个 default 分支
switch 语句用于基于不同条件执行不同动作,每一个 case 分支都是唯一的,从上至下逐一测试,直到匹配为止。 switch 语句执行的过程从上至下,直到找到匹配项,匹配项后面也不需要再加 break。 switch 默认情况下 case 最后自带 break 语句,匹配成功后就不会执行其他 case,如果我们需要执行后面的 case,可以使用 fallthrough 。 // select 语句
select {
case communication clause :
statement(s);
case communication clause :
statement(s);
// 可以定义任意数量的 case
default : // 可选
statement(s);
} // select 随机执行一个可运行的 case。如果没有 case 可运行,它将阻塞,直到有 case 可运行。
每个 case 都必须是一个通信
所有 channel 表达式都会被求值
所有被发送的表达式都会被求值
如果任意某个通信可以进行,它就执行,其他被忽略。
如果有多个 case 都可以运行,Select 会随机公平地选出一个执行。其他不会执行。
否则:
如果有 default 子句,则执行该语句。
如果没有 default 子句,select 将阻塞,直到某个通信可以运行;Go 不会重新对 channel 或值进行求值。
Go 没有三目运算符,所以不支持 ?: 形式的条件判断
循环语句
// for 循环
for index, elem := range nums {
// do something
} for { // 死循环
// do something
} // break & continue 语句
for _, elem := range nums {
switch elem{
case "":
contiue
case "bye", "quit":
break
default:
fmt.Println("Hello World")
}
} // goto 语句: 无条件地转移到代码中 goto语句 指定的标签中 执行标签内代码
func main() { for x := ; x < ; x++ { for y := ; y < ; y++ { if y == {
// 跳转到标签
goto breakHere
} }
} // 手动返回, 避免执行进入标签
return // 标签
breakHere:
fmt.Println("done")
}
五、数组
- go 的数组内所有元素都是同一类型、是固定长度的有序集合
- 声明语法: var aryName [arySize]elemType
- 相同类型的两个数组支持 “!=” 和 “==” 比较,但不能比较两个数组的大小
- 数组的指针:*[3]int; 指针数组:[2]*int
// 声明数组
var ary[] int // 数组赋值
ary[] = // 初始化数组
var balanceSize = [] float32{, 2.0, 3.1, 5.5, 6.2}
var balanceSize = [...]float32{100, 2.0, 3.1, 5.5, 6.2} // 可省略长度,`...`的方式,会自动根据元素个数来计算长度
// 声明多维数组并赋值
var secondly [][] int
for k:=; k<len(secondly); k++ {
for m:=; m<len(secondly[k]); m++ {
secondly[k][m] = k + m +
}
} // 初始化多维数组
var secondlyArray = [][] int{
{, , },
{, , },
} // 索引访问数组元素
fmt.Println(balanceSize[]) // 索引设置数组元素值
balanceSize[] = 22.2 // 返回数组长度
fmt.Println(len(balanceSize))
六、切片
- 切片的长度是可变的,声明时无需指定切片长度,可以使用数组的方式设置、访问元素、len 获取切片的长度
- 额外的操作:
- append() 追加元素,返回一个拥有新元素的新切片,append不会改变原切片,而是生成了一个新切片。
- 取切片操作:slice[start:end];包含 start,而不包含end
- 也可创建多维切片,拥有以上所有操作
- 数组和切片的定义方式的区别在于
[]
之中是否有固定长度
或者推断长度标志符...
// 声明切片: var sliceName []sliceType
var sliceTest [] int // 第一种方式
sliceTest := make([]string, ) // 创建一个长度为3,存储字符串的切片 // 追加元素
sliceTest = append(sliceTest, "power")
sliceTest = append(sliceTest, "top", "one") // 取切片
newSlice := sliceTest[:] // 取前两个元素
newSlice := sliceTest[:] // 取所有元素
newSlice := sliceTest[:] // 取索引为1的元素到索引为4的元素 // 同时声明和初始化一个切片
t := []string{"g", "h", "i"} // 创建二维切片
twoD := make([][]int, )
for i := ; i < ; i++ {
innerLen := i +
twoD[i] = make([]int, innerLen)
for j := ; j < innerLen; j++ {
twoD[i][j] = i + j
}
}
fmt.Println("2d: ", twoD)
} // copy
var nilSlice []int
nilSlice = append(nilSlice, , , , , )
copySlice := make([]int, len(nilSlice), (cap(nilSlice))*)
copy(copySlice, nilSlice)
七、字典 map
// 声明 map :var variable map[keyType]valueType
var mapVariable map[string]string // 默认为 map[] nil // make函数 定义map
mapVariable := make(map[string]string) // make 定义并初始化
test := map[string]float32{"a": , "b": , "c": } // map 是一种引用,两个map指向同一底层,一个修改,另一个也变化
otherTest := test
otherTest["c"] =
fmt.Println("modify otherTest: ", otherTest)
fmt.Println("modify test: ", test) // [Output]:modify otherTest: map[a:1 b:2 c:6]
// [Output]:modify test: map[a:1 b:2 c:6] // 添加键值
mapVariable["s"] = "\u5bb6\u8431"
mapVariable["h"] = "\u99a5\u7504"
mapVariable["e"] = "\u5609\u6866" // 遍历取出键值
for key, value := range mapVariable{
fmt.Println(key, value)
} // 判断是否存在某键
name, ok := mapVariable["s"] // name:若key存在返回所对应的value,ok:此key是否存在(bool型) // 删除键值
delete(map_variable1, "she") // 若key不存在,则忽略 // key 对应 多个 value:切片
mp1 := make(map[int][]int)
mp2 := make(map[int]*[]int)
八、make & new
make
- make用于内建类型(map、slice、channel)的内存分配
- make(T,args)与new(T)有着不同的功能,make只能创建slice,map,channel,并且返回一个有初始值(非零)的T类型,而不是*T
new
- new用于各种类型的内存分配【new返回指针】
- new(T)分配了零值填充的T类型的内存空间,并且返回其地址,即一个*T类型的值(GO语言的术语:返回了一个指针,指向新分配的类型T的零值)
ending
- 使用 new 创建的某个类型的对象,返回的是 内存地址;使用 make 创建的是三种类型之一的对象,返回的是带有初始值的value
- new 负责分配内存,new(T) 返回 *T:代表的是 T类型的指针,是一个指向零值的 T 类型指针
- make 负责初始化值,make(T) 返回初始化后的 T ,而非指针,make 仅适用于slice,map 和channel
// make & new 的区别 // make
slices := make([]int, )
fmt.Println("slices: ", slices) maps := make(map[int]int)
fmt.Println("maps: ", maps)
// 【Output】:slices: [0 0]
// 【Output】:maps: map[] // 声明结构体
type Info struct {
} // new
num := new(int)
fmt.Println("num: ", num) structVariable := new(Info)
fmt.Println("structVariable", structVariable) //【Output】:num: 0xc00000a120
//【Output】:structVariable &{} // make & new 区别的实例
type Foo struct { // 声明结构体
weight float64
age int
} // 声明
var foo1 Foo
fmt.Println("foo1: ", foo1)
foo1.age =
fmt.Println("foo1: ", foo1) fmt.Println() // 定义
foo2 := Foo{}
fmt.Println("foo2: ", foo2)
foo2.age =
fmt.Println("foo2: ", foo2) fmt.Println() // make 只能创建 channel、slice、map // & 取址
foo3 := &Foo{}
fmt.Println("foo3: ", foo3)
fmt.Println("foo3: ", *foo3)
foo3.age =
fmt.Println("foo3: ", foo3) fmt.Println() // new
foo4 := new(Foo)
fmt.Println("foo4: ", foo4)
fmt.Println("foo4: ", *foo4)
foo4.age =
fmt.Println("foo4: ", foo4) fmt.Println() var foo5 *Foo = &Foo{}
fmt.Println("foo5: ", foo5)
fmt.Println("foo5: ", *foo5)
foo5.age =
fmt.Println("foo5: ", foo5) // 以下是输出结果
foo1: { }
foo1: { } foo2: { }
foo2: { } foo3: &{ }
foo3: { }
foo3: &{ } foo4: &{ }
foo4: &{ } foo5: &{ }
foo5: &{ }
注:foo1 & foo2 为相同的类型,输出的都是 结构体Foo类型的值 ==> {0 0} 由于没有给字段赋值,输出的都是初始值
foo3 & foo4 & foo5 为相同的类型,输出的都是 结构体Foo类型的内存地址(指针) ==> &{0 0} 只有在前面加了 * 之后才是取到了他的值:*foo3、*foo4、*foo5
go 学习 (二):基本语法的更多相关文章
- QML学习(二)——<QML语法>
一.Qml类型 QML类型分为三类:基本类型.QML对象类型以及JavaScript类型 1 基本类型 我们可以再qt帮助文档中搜索基本类型查看 基本类型的概念是相对于QML对象类型而言的,QML 对 ...
- XPath 学习二: 语法
XPath 使用路径表达式来选取 XML 文档中的节点或节点集.节点是通过沿着路径 (path) 或者步 (steps) 来选取的. 下面列出了最有用的路径表达式: 表达式 描述 nodename 选 ...
- ReactJS入门学习二
ReactJS入门学习二 阅读目录 React的背景和基本原理 理解React.render() 什么是JSX? 为什么要使用JSX? JSX的语法 如何在JSX中如何使用事件 如何在JSX中如何使用 ...
- day 82 Vue学习二之vue结合项目简单使用、this指向问题
Vue学习二之vue结合项目简单使用.this指向问题 本节目录 一 阶段性项目流程梳理 二 vue切换图片 三 vue中使用ajax 四 vue实现音乐播放器 五 vue的计算属性和监听器 六 ...
- day 81 Vue学习二之vue结合项目简单使用、this指向问题
Vue学习二之vue结合项目简单使用.this指向问题 本节目录 一 阶段性项目流程梳理 二 vue切换图片 三 vue中使用ajax 四 vue实现音乐播放器 五 vue的计算属性和监听器 六 ...
- redis命令学习(二) · THIS SPACE
列表(Lists)操作命令 Redis列表是简单的字符串列表,按照插入顺序排序. 你可以添加一个元素导列表的头部(左边)或者尾部(右边)LPUSH命令插入一个新的元素导头部,而RPUSH插入一个新元素 ...
- emberjs学习二(ember-data和localstorage_adapter)
emberjs学习二(ember-data和localstorage_adapter) 准备工作 首先我们加入ember-data和ember-localstorage-adapter两个依赖项,使用 ...
- JavaScript学习02 基础语法
JavaScript学习02 基础语法 JavaScript中很多基础内容和Java中大体上基本一样,所以不需要再单独重复讲了,包括: 各种算术运算符.比较运算符.逻辑运算符: if else语句.s ...
- TweenMax动画库学习(二)
目录 TweenMax动画库学习(一) TweenMax动画库学习(二) TweenMax动画库学习(三) Tw ...
- Hbase深入学习(二) 安装hbase
Hbase深入学习(二) 安装hbase This guidedescribes setup of a standalone hbase instance that uses the local fi ...
随机推荐
- 如何Dockerize您的端到端验收测试
本文作为使用Selenium Docker映像以及CodeceptJS和Express服务器的“操作方法”指南. 其中,我们将涵盖: 什么是E2E验收测试? 为什么要使用Docker? 松散耦合的测试 ...
- mysql 启动 && 停止
启动:service mysql start关闭:service mysql stop查进程:ps aux | grep mysql杀进程:kill -9 mysqlID Good Good Stud ...
- 嵌入式02 STM32 实验05 蜂鸣器
蜂鸣器:是一种一体化结构的电子讯响器.主要分为分压式蜂鸣器和电磁式蜂鸣器两种类型. 一.有源/无源蜂鸣器(不是指是否带电源,而是有没有自带震荡电路) 1.有源蜂鸣器:有源蜂鸣器自带震荡电路,一通电就会 ...
- UML交互图
UML 交互图主要包括对象和消息两类元素,创建交互图的过程实际上就是向对象分配任务的过程,是可视化系统的交互行为. UML 交互图包括两种:序列图和协作图. 序列图:显示对象之间的关系,强调对象之间消 ...
- 修改 Delphi 10.3.3 IDE 字体和字体大小
Delphi 10.2.2 之前,可以通过 IDE视觉设置的系统注册表项 修改字体和字体大小,因为 Delphi 10.2.2 IDE增加了主题,主题包含了字体信息, 此方法失效了.对于高分辨率屏幕, ...
- C语言:求π
1835: 圆的面积 本题的关键在于如何求π: 今天先给给大家介绍一种针对本题的方法——利用反三角函数求π. 在高数中arcsin(0)=arccos(1)=π,不过编译器中并没有arcsin和arc ...
- Go基础编程实践(一)—— 操作字符串
修剪空格 strings包中的TrimSpace函数用于去掉字符串首尾的空格. package main import ( "fmt" "strings" ) ...
- 关于使用KubeSphere中的docker配置Harbor仓库http访问docker login登陆报错的解决办法
# 先进入harbor目录中,停止harbor docker-compose stop # 然后修改docker相关文件 # 第一种方式:修改/etc/docker/daemon.json { &qu ...
- C# vb .net实现圆角矩形特效滤镜
在.net中,如何简单快捷地实现Photoshop滤镜组中的圆角矩形效果呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第 ...
- 【夯实基础】- Integer.valueof()和Integer.parseInt()的区别
今天在看公司代码的时候,看到有人在将 String 转为 int 时,用到了Integer.parseInt(String s)方法,我一直用的是Integer.valueOf(String s)方法 ...