一. Go基础语法
- Go语言的代码结尾不需要分号。
- Go语言区分大小写。
- Go语言和Java、C、C++等语言一样,属于静态语言。
- Go语言会自动推断类型。
1. 常见数据类型
变量 | 描述 | 默认初始值 | 范围 |
---|---|---|---|
bool | 布尔类型 | false | |
string | 字符串类型 | 空 | |
int | 整型 | 0 | |
int8 | 整型 | 0 | |
int16 | 整型 | 0 | |
int32 | 整型 | 0 | |
int64 | 整型 | 0 | |
uint | 无符号整型 | 0 | |
uint8 | 无符号整型 | 0 | |
uint16 | 无符号整型 | 0 | |
uint32 | 无符号整型 | 0 | |
uint64 | 无符号整型 | 0 | |
uintptr | 无符号整型 | 0 | |
byte | // uint8 的别名 ASCII 码的一个字符,字符类型 | ||
rune | // int32 的别名 代表一个 Unicode 码,字符类型 | ||
float32 | 浮点型 | 0.0 | |
float64 | 浮点型 | 0.0 | |
complex64 | 32 位实数和虚数,复数类型 | ||
complex128 | 64 位实数和虚数,复数类型 |
2. 常用命名规则
类别 | 一般命名规则 |
---|---|
源码文件 | 全部小写英文单词,每个单词之间使用下划线分割 |
包 | 简短的小写英文单词,不能和Go内置标准库相同 |
变量 | 驼峰式命名法 |
常量 | 全部大写英文单词,每个单词之间使用下划线分割 |
结构体 | 驼峰式命名法 |
接口 | 驼峰式命名法 |
常用规则
- 对于对外可见的变量,使用大驼峰法;
- 对于对外不可见的变量,使用小驼峰法。
- 布尔类型变量/常量,通常以is、allow、has、can等开头;
3. 变量
变量:源于数学,是计算机语言中能储存计算结果或能表示值的抽象概念,它的值通常是可变的,变量是一段或多段用来存储数据的内存。
变量必须先声明再使用,默认自动赋初始值,指针为 nil ,所有的内存在 Go 中都经过初始化。
3.1 变量命名
单行声明
// 变量初始化标准格式
var 变量名 类型 = 表达式
// 单行
var 变量名 变量类型
var userAge int = 20
批量多行声明
//多行,批量声明
var (
nums int
name string
income []float64
funcname func() bool
)
简短声明
// 简短命名方式,定义及初始化,不能提供数据类型,在函数内部使用。
// 自动推断类型
名字 := 表达式
// 此处name和age若已经声明,则不能用:=这种方式
name,age:="myname",20
遵循驼峰命名。不要和关键字和保留字相同。
小驼峰命名:首个单词小写,每个新单词的首字母大写。如startDate
大驼峰命名:所有单词的首字母均大写。CONST_NAME
4. 常量
常量:是一个简单值的标识符,在程序运行时,不会被修改的量。
常量的运算都可以在编译期完成,编译时期可发现。
常量必须先声明在使用。
4.1 常量命名
对于常量,通常单词均用大写字母来表示,每个字母之间使用下划线来分割。
声明方式和变量的声明方式类似。
// 隐式类型,自动推断类型,浮点类型
const PI = 3.1415926
// 显式类型
const NAME string = "root"
4.2 iota 常量生成器
生成一组以相似规则初始化的常量
package main
import "fmt"
func main() {
const (
A = iota // 0
B // 1
C // 2
D = 0 // 0, 被打断后,后续值不变,直到用iota显示恢复
E // 0
F // 0
G = iota // 6,显示恢复,iota接着累加,中间打断不中断累加
H // 7
I = iota * 2 // 16,iota不变,变更常量表达式,后续保持表达式
J // 18
)
fmt.Println(C, D, E, F, J)
}
结果
2 0 0 0 18
4.3 无类型的常量
无类型的布尔型、无类型的整数、无类型的字符、无类型的浮点数、无类型的复数、无类型的字符串。
编译器为这些没有明确基础类型的常量提供比基础类型更高精度的算术运算,当赋值给特定类型时精度会有影响。
5. 字符串类型
一个字符串是一个不可改变的字节序列(UTF-8)。
当字符为 ASCII 码表上的字符时则占用 1 个字节,其它字符根据需要占用 2-4 个字节。
字符串是一种值类型,且值不可变。
5.1 字符串定义
单行用双引号,多行可以用反引号
注意:使用反引号里面所有的转义字符均无效,文本将会原样输出
package main
import "fmt"
func main() {
// 单行字符串
var st string = "单行字符串"
fmt.Println(st)
// 多行字符串
const str = `第一行
第二行
\r\n
`
fmt.Println(str)
}
结果
单行字符串
第一行
第二行
\r\n
5.2 字符串拼接
使用“+”号拼接
package main
import "fmt"
func main() {
s1 := "字符串1"
s2 := "字符串2"
fmt.Println("s1和s2: ", s1, s2)
s3 := s1 + s2
fmt.Println("s3: ", s3)
}
结果
s1和s2: 字符串1 字符串2
s3: 字符串1字符串2
5.3 转义
特殊符号需要使用“\”号进行转义,常见转义字符如\n 换行 \t制表符,\u 或 \U:Unicode 字符
// 如双引号需要转义,加\
package main
import "fmt"
func main() {
var text string = "双引号需要转义的:\"字符串\"\n换一下行"
fmt.Println(text)
}
// 结果
双引号需要转义的:"字符串"
换一下行
6.指针
指针存放数据的“实际地址”,使用指针可以直接访问内存中的数据。
指针变量:存放指针值
6.1 指针类型
1.类型指针
减少内存开销不创建数据副本,传递数据时使用指针。类型指针不能进行偏移和运算,避免数据被非法修改的风险,利于垃圾回收机制及时找到并进行回收;
2.切片指针
切片由指向起始元素的指针、元素数量和总容量构成。当访问切片发生越界时,会发生宕机并输出堆栈信息。宕机是可以恢复的,而崩溃只能导致程序停止运行。
6.2 指针使用场景
1.反射修改变量值
2.获取变量内存地址(使用"&“)
3.获取某地址对应的值(使用”*")
4.new()函数创建指针变量(在无需变量名或必须要传递指针变量值中使用)。
格式:new(数据类型)
通常使用" & “运算符获取变量内存地址,使用” * "运算符获取某地址对应的值,例
使用&和*
package hello1
import "testing"
func TestPtr(t *testing.T){
//声明和赋值整型变量testA
var testA int = 3
//获取testA的地址,并赋值给testAPtr变量(testAPtr的类型是指针类型)
testAPtr := &testA
//输出testAPtr变量的值(将输出内存地址)
t.Log(testAPtr)
//获取testAPtr(指针变量)表示的实际数据值,并赋值给testAPtrValue变量(整型变量)
testAPtrValue := *testAPtr
//输出testAPtrValue变量(整数型变量)的值
t.Log(testAPtrValue)
}
// 测试
E:\workspace\GO_PATH\wincmd_space>go test -v -run TestPtr$ hello_test.go
=== RUN TestPtr
hello_test.go:22: 0xc000094178
hello_test.go:26: 10
--- PASS: TestPtr (0.00s)
PASS
ok command-line-arguments 1.300s
使用new()函数
直接创建指针变量,在内存中创建了某种类型匿名的变量。无数据副本产生,取值和赋值都使用指针操作。
func TestNewMethod(t *testing.T){
//使用new()函数创建名为testAPtr指针类型变量,表示int32型值,分配内存
testAPtr := new(int32)
//修改testAPtr表示的实际数据值
*testAPtr = 11
//获取testAPtr表示的实际数据值
t.Log(*testAPtr)
}
// 输出11
E:\workspace\GO_PATH\wincmd_space>go test -v -run TestNewMethod$ hello_test.go
=== RUN TestNewMethod
hello_test.go:35: 11
--- PASS: TestNewMethod (0.00s)
PASS
ok command-line-arguments 1.391s