Go基础—1.基本语法结构

TOC

一、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 逗号运算符 , 从左到右