Go基础—1.基本语法结构
一、Go语法规则
Go语言的基本结构组成:
1.包声明、2.引入包、3.函数、4.变量、5、语句和表达式、6.注释
☆第一个程序:Helloworld☆
package main
import "fmt"
func main() {
// Println 换行输出,Print 不换行输出
fmt.Println("Hello, World!")
fmt.Print("Hello, Go!")
fmt.Print("Hello, Python!")
}
Go标记
Go 程序可以由多个标记组成,可以是关键字,标识符,常量,字符串,符号。如以下 GO 语句由 6 个标记组成
fmt.Println("Hello, World!")
/* 6个标记是每行一个
1. fmt
2. .
3. Println
4. (
5. "Hello, World!"
6. )
*/
行分隔符
在Go程序中,一行代表一个语句结束。每个语句不需要像其它语言一样以分号 ; 结尾,因为这些工作都将由 Go 编译器自动完成。
如果你想写到一行则需要用 ; 符号进行人为分割,以下为两个语句:
fmt.Println("Hello, World!")
fmt.Println("Hello, Go!")
注释
一共分为单行注释和多行注释
// 单行注释
/*
我是多行注释
1111
2222
*/
标识符
标识符用来命名变量、类型等。标识符由一个或者多个自负、数字、下划线组成的序列(第一个字符不能是数字,只能是字母或者下划线)
有效标识符:mahesh Ahdh move_name a_123 _temp
无效标识符:1ab(数字开头) a+b(出现运算符) case(Go语言关键字)
字符串连接
Go语言的字符串可以通过’+'实现连接
fmt.Println("你好," + "Go")
二、Go数据类型
变量类型和变量赋值
Go变量类型主要有:
bool
string
int、int8、int16、int32、int64
uint、uint8、uint16、uint32、uint64、uintptr
byte // uint8 的别名
rune // int32 的别名 代表一个 Unicode 码
float32、float64
complex64、complex128
变量进行赋值
当一个变量被声明之后,系统自动赋予它该类型的零值:int 为 0,float 为 0.0,bool 为 false,string 为空字符串,指针为 nil 等
变量声明和赋值的标准格式:
// 变量声明
var 变量名 变量类型
// 变量初始化赋值
var 变量名 类型 = 表达式
变量初始化声明使用var关键字
// 单个变量赋值
var a = 100
var b int = 200
// 多个变量赋值
var c,d int = 100,200
fmt.Println("a:",a,"b:",b,"c:",c,"d:",d)
// 批量格式
var (
e = 1
f = "dsandjan"
g float32 = 3.14
h bool = false
)
fmt.Println("e:",e,"f:",f,"g:",g,"h:",h)
简短格式:
// 使用:=进行变量初始化赋值,名字 := 表达式
func main() {
x := 100
a,s := 1, "abc"
}
如果变量没有初始化赋值,则系统会默认设置变量的值。
数值类型默认值为:0
布尔类型默认值为:false
字符串默认值为:""(空字符)
以下几种类型为:null
var a *int
var a []int
var a map[string] int
var a chan int
var a func(string) int
var a error // error 是接口
常量类型和赋值
常量是一个简单值的标识符,在程序运行时,不会被修改的量。
常量中的数据类型只可以是布尔型、数字型(整数型、浮点型和复数)和字符串型。
定义常量:
const 常量名 常量类型 = 常量值
举例定义常量(两种定义方式):
# 显式类型定义
const a string = "test"
# 隐式类型定义,省略类型说明,编译器根据值来推断类型
const b = "test"
Go指针
指针在Go中的两个核心概念:
- 1.类型指针,允许对这个指针类型的数据进行修改,传递数据可以直接使用指针,而无须拷贝数据,类型指针不能进行偏移和运算。
- 2.切片,由指向起始元素的原始指针、元素数量和容量组成。
| 符号 | 符号名称 | 符号作用 |
|---|---|---|
| & | 返回变量存储地址 | &a; 将给出变量的实际地址 |
| * | 指针变量 | *a; 是一个指针变量 |
1.认识指针地址和指针类型
指针变量可以指向任何一个值的内存地址,它所指向的值的内存地址在 32 和 64 位机器上分别占用 4 或 8 个字节,占用字节的大小与所指向的值的大小无关。
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。
获取指针地址
【示例】代码如下所示:
package main
import "fmt"
func main() {
var a int = 1
var b string = "hello"
fmt.Printf("a的指针地址为: %p,b的指针地址为: %p\n", &a, &b)
}
/* 运行结果如下
a的指针地址为: 0x1400000e0d0,b的指针地址为: 0x14000010040
*/
2.从指针获取指针指向的值
当使用&操作符对普通变量进行取地址操作并得到变量的指针后,可以对指针使用*操作符,也就是指针取值。
获取指针指向地址的值
【示例】代码如下所示:
package main
import "fmt"
func main() {
// 赋值一个字符串类型的变量
var str = "My name is alice!!!"
// 对字符串取地址, ptr类型为*string
ptr := &str
// 打印ptr的类型、指针地址
fmt.Printf("ptr type: %T, address: %p\n", ptr, ptr)
// 对指针进行取值操作
value := *ptr
// 取值后的类型和指向变量的值
fmt.Printf("value type: %T, value data: %s\n", value, value)
}
/* 运行结果如下
ptr type: *string, address: 0x14000104020
value type: string, value data: My name is alice!!!
*/
3.使用指针修改值
通过指针不仅可以取值,也可以修改值。
使用指针交换变量值
【示例】代码如下所示:
package main
import "fmt"
func main() {
var a, b int = 1, 2
x := &a
y := &b
t := *x
*x = *y
*y = t
fmt.Printf("a和b交换之后的值为: a=%d, b=%d", a, b)
}
/* 运行结果如下
a和b交换之后的值为: a=2, b=1
*/
4.创建指针的另外方法—new()函数
new()可以创建对应类型的指针,例子如下:
str := new(string)
*str = "我是一个指针"
fmt.Println(*str)
三、Go运算符
算术运算符
| 符号 | 符号名称 | 符号作用 |
|---|---|---|
| + | 加 | 两个对象相加 |
| - | 减 | 得到负数或是一个数减去另一个数 |
| * | 乘 | 两个数相乘或是返回一个被重复若干次的字符串 a * b 输出结果 210 |
| / | 除 | 两个对象相除 |
| % | 取余 | 返回除法的余数 |
使用算术运算符的例子
【示例】代码如下所示:
package main
import "fmt"
func main() {
var a int = 21
var b int = 10
var c int
c = a + b
fmt.Printf("a + b 的值为: %d\n", c)
c = a - b
fmt.Printf("a - b 的值为: %d\n", c)
c = a * b
fmt.Printf("a * b 的值为: %d\n", c)
c = a / b
fmt.Printf("a / b 的值为: %d\n", c)
c = a % b
fmt.Printf("a + b 的值为: %d\n", c)
a++
fmt.Printf("a++ 的值为: %d\n", a)
a = 21 // 为了方便测试,a 这里重新赋值为 21
a--
fmt.Printf("a-- 的值为: %d\n", a)
}
/* 运行结果如下
a + b 的值为: 31
a - b 的值为: 11
a * b 的值为: 210
a / b 的值为: 2
a + b 的值为: 1
a++ 的值为: 22
a-- 的值为: 20
*/
关系运算符
| 符号 | 符号名称 | 符号作用 |
|---|---|---|
| == | 等于 | 比较对象是否相等 |
| != | 不等于 | 比较两个对象是否不相等 |
| > | 大于 | 返回x是否大于y |
| < | 小于 | 返回x是否小于y。 |
| >= | 大于等于 | 返回x是否大于等于y。 |
| <= | 小于等于 | 返回x是否小于等于y。 |
使用关系运算符的例子
【示例】代码如下所示:
package main
import "fmt"
func main() {
var a int = 21
var b int = 10
//判断a和b是否相等
if a == b {
fmt.Printf("a 等于 b\n")
} else {
fmt.Printf("a 不等于 b\n")
}
//判断a和b值的大小
if a < b {
fmt.Printf("a 小于 b\n")
} else {
fmt.Printf("b 小于 a\n")
}
// 重新赋值a和b
a = 5
b = 20
if a >= b {
fmt.Printf("a 大于等于 b\n")
} else {
fmt.Printf("a 小于 b\n")
}
}
/* 运行结果如下
a 不等于 b
b 小于 a
a 小于 b
*/
逻辑运算符
| 符号 | 符号名称 | 符号作用 |
|---|---|---|
| && | 逻辑 AND 运算符 | x && y,如果 x 和 y 都满足条件 |
| || | 逻辑 OR 运算符 | x || y,如果 x 或 y 满足一个条件 |
| ! | 逻辑 NOT 运算符 | ! x,如果 x 不满足条件 |
使用逻辑运算符
【示例】代码如下所示:
package main
import "fmt"
func main() {
var a bool = false
var b bool = true
if a && b {
fmt.Printf("a && b 条件为 true\n")
} else {
fmt.Printf("a && b 条件为 false\n")
}
if !(a && b) {
fmt.Printf("!(a && b) 条件为 true\n")
}
}
/* 运行结果如下
a && b 条件为 false
!(a && b) 条件为 true
*/
位运算符
| 符号 | 符号名称 | 符号作用 |
|---|---|---|
| & | 按位与运算符 | 参与运算的两个值,如果两个相应位都为1,则该位的结果为1,否则为0 (a & b) 输出结果 12 ,二进制解释: 0000 1100 |
| | | 按位或运算符 | 只要对应的二个二进位有一个为1时,结果位就为1。 (a | b) 输出结果 61 ,二进制解释: 0011 1101 |
| ^ | 按位异或运算符 | 当两对应的二进位相异时,结果为1 (a ^ b) 输出结果 49 ,二进制解释: 0011 0001 |
| ~ | 按位取反运算符 | 对数据的每个二进制位取反,即把1变为0,把0变为1。~x 类似于 -x-1 (~a ) 输出结果 -61 ,二进制解释: 1100 0011, 在一个有符号二进制数的补码形式。 |
| << | 左移动运算符 | 运算数的各二进位全部左移若干位,由"<<"右边的数指定移动的位数,高位丢弃,低位补0。 a << 2 输出结果 240 ,二进制解释: 1111 0000 |
| >> | 右移动运算符 | 把">>“左边的运算数的各二进位全部右移若干位,”>>"右边的数指定移动的位数 a >> 2 输出结果 15 ,二进制解释: 0000 1111 |
使用位运算
【示例】代码如下所示:
package main
import "fmt"
func main() {
var (
A uint = 60 //0011 1100
B uint = 13 //0000 1101
C uint = 0 //0000 0000
)
C = A & B /* 12 = 0000 1100 */
fmt.Printf("A & B 的值为: %d\n", C)
C = A | B /* 61 = 0011 1101 */
fmt.Printf("A | B 的值为: %d\n", C)
C = A ^ B /* 49 = 0011 0001 */
fmt.Printf("A ^ B 的值为: %d\n", C)
C = A << 2 /* 240 = 1111 0000 */
fmt.Printf("A << 2 的值为: %d\n", C)
C = A >> 2 /* 15 = 0000 1111 */
fmt.Printf("A >> 2 的值为: %d\n", C)
}
/* 运行结果如下
A & B 的值为: 12
A | B 的值为: 61
A ^ B 的值为: 49
A << 2 的值为: 240
A >> 2 的值为: 15
*/
赋值运算符
| 符号 | 符号名称 | 符号作用 |
|---|---|---|
| = | 简单的赋值运算符 | c = a + b 将 a + b 的运算结果赋值为 c |
| += | 加法赋值运算符 | c += a 等效于 c = c + a |
| -= | 减法赋值运算符 | c -= a 等效于 c = c - a |
| *= | 乘法赋值运算符 | c *= a 等效于 c = c * a |
| /= | 除法赋值运算符 | c /= a 等效于 c = c / a |
| %= | 取模赋值运算符 | c %= a 等效于 c = c % a |
| <<= | 左移后赋值 | C <<= 2 等于 C = C << 2 |
| >>= | 右移后赋值 | C >>= 2 等于 C = C >> 2 |
| &= | 按位与后赋值 | C &= 2 等于 C = C & 2 |
| ^= | 按位异或后赋值 | C ^= 2 等于 C = C ^ 2 |
| |= | 按位或后赋值 | C |= 2 等于 C = C | 2 |
使用赋值运算符
【示例】代码如下所示:
package main
import "fmt"
func main() {
var (
a int
c int
)
a = 2
fmt.Println("= 运算符实例, a 的值为: ", a)
c += a
fmt.Println("+= 运算符实例, c 的值为: ", c)
c -= a
fmt.Println("-= 运算符实例, c 的值为: ", c)
c *= a
fmt.Println("*= 运算符实例, c 的值为: ", c)
c /= a
fmt.Println("/= 运算符实例, c 的值为: ", c)
c = 200
c <<= 2
fmt.Println("<<= 运算符实例, c 的值为: ", c)
c >>= 2
fmt.Println(">>= 运算符实例, c 的值为: ", c)
c &= 2
fmt.Println("&= 运算符实例, c 的值为: ", c)
c ^= 2
fmt.Println("^= 运算符实例, c 的值为: ", c)
c |= 2
fmt.Println("|= 运算符实例, c 的值为: ", c)
}
/* 运行结果如下
= 运算符实例, a 的值为: 2
+= 运算符实例, c 的值为: 2
-= 运算符实例, c 的值为: 0
*= 运算符实例, c 的值为: 0
/= 运算符实例, c 的值为: 0
<<= 运算符实例, c 的值为: 800
>>= 运算符实例, c 的值为: 200
&= 运算符实例, c 的值为: 0
^= 运算符实例, c 的值为: 2
|= 运算符实例, c 的值为: 2
*/
★Go运算符的优先级
注意:优先级越大运算符就拥有越高的优先级。
因此由上至下代表优先级由高到低。
| 优先级 | 分类 | 运算符 | 结合性 |
|---|---|---|---|
| 14 | 后缀运算符 | ( )、[ ]、-> | 从左到右 |
| 13 | 单目运算符 | !、*(指针)、& 、++、–、+(正号)、-(负号) | 从右到左 |
| 12 | 乘法/除法/取余 | *(乘号)、/、% | 从左到右 |
| 11 | 加法/减法 | +、- | 从左到右 |
| 10 | 位移运算符 | <<、>> | 从左到右 |
| 9 | 关系运算符 | <、<=、>、>= | 从左到右 |
| 8 | 相等/不等 | ==、!= | 从左到右 |
| 7 | 按位与 | & | 从左到右 |
| 6 | 按位异或 | ^ | 从左到右 |
| 5 | 按位或 | | | 从左到右 |
| 4 | 逻辑与 | && | 从左到右 |
| 3 | 逻辑或 | | | 从左到右 |
| 2 | 赋值运算符 | =、+=、-=、*=、/=、 %=、 >=、 <<=、&=、^=、|= | 从右到左 |
| 1 | 逗号运算符 | , | 从左到右 |