Go语言定义变量
常见定义方法
- 使用
var
:语法为var 变量名类型= 表达式
,例如var name string = "zhangsan"
。 - 类型推导(函数内部):语法为
变量名:= 表达式
,例如n := 10
;注意短变量只能用于声明局部变量,不能用于全局变量声明
fmt 包及打印方法
- 使用前提:需要引入 fmt 包,即
import "fmt"
。 - Print 与 Println 的区别
- 多值输入时,Println 会在值中间加空格,Print 不会,例如
fmt.Println("go", "python", "php", "javascript")
输出为go python php javascript
,fmt.Print("go", "python", "php", "javascript")
输出为gopythonphpjavascript
。 - 换行方面,Println 会自动换行,Print 不会,例如连续使用
fmt.Println("hello")
和fmt.Println("world")
,输出结果为分行的hello
和world
;而连续使用fmt.Print("hello")
和fmt.Print("world")
,输出结果为helloworld
。
- 多值输入时,Println 会在值中间加空格,Print 不会,例如
- Println 与 Printf 的区别:Printf 是格式化输出,需使用占位符,如
%d
表示数字的十进制表示,且占位符与后面的变量一一对应,使用更灵活;例如fmt.Printf("a=%d,b=%d,c=%d", a, b, c)
可输出a=10,b=20,c=30
,而fmt.Println("a=", a, ",b=", b, ",c=", c)
输出为a= 10 ,b= 20 ,c= 30
。 - 更多占位符参考:可访问
http://docscn.studygolang.com/pkg/fmt/
注释
快捷注释方式:Windows 系统使用ctrl+/
,Mac 系统使用command+/
- 注释形式
- 多行注释:
/* 这是一个注释 */
- 单行注释:
// 这是一个注释
。
- 多行注释:
Go 变量、常量及命名规则
变量声明方式
- 使用
var
声明:语法为var 变量名称 type
,如var name string
、var age int
等;也可在声明时赋值,如var username="张三"
、var age int =20
。 - 一次定义多个变量:
var identifier1, identifier2 type
,如var username, sex string
;也可在声明时赋值,如var a, b, c, d = 1, 2, 3, false
。 - 批量声明变量并可指定类型或赋值:如
var (a string; b int; c bool)
,也可在批量声明时直接赋值,如var (a string = "张三"; b int = 20; c bool = true)
。 - 变量初始化:声明时会自动初始化为类型默认值,如整型和浮点型默认值为 0,字符串为空字符串等;也可手动指定初始值,标准格式为
var 变量名类型= 表达式
,还可一次初始化多个变量,如var name, age = "zhangsan", 20
。 - 类型推导:省略变量类型,编译器根据等号右边值推导类型,如
var name = "Q1mi"
。 - 短变量声明法:函数内部用
:=
声明并初始化局部变量,不能用于全局变量,如n := 10
,也可一次声明多个,如m1, m2, m3 := 10, 20, 30
- 匿名变量:用
_
表示,用于忽略多重赋值中的某个值,不占用命名空间,无重复声明问题,如_, username := getInfo()
。 - 注意事项:函数外语句须以关键字开头;
:=
不能在函数外使用;_
多用于占位忽略值
常量
- 定义:恒定不变的值,声明类似变量但用
const
,定义时必须赋值,如const pi = 3.1415
;可同时声明多个,如const (pi = 3.1415; e = 2.7182)
;同时声明多个时省略值则与上一行相同,如const (n1 = 100; n2; n3)
中 n2、n3 均为 100。 - 结合 iota 使用:iota 是常量计数器,仅在常量表达式中使用,const 出现时重置为 0,每新增一行常量声明计数一次。如
const a = iota
中 a=0;可跳过某些值、中间插队、多个定义在一行等,如const (n1 = iota; n2 = 100; n3 = iota)
中 n1=0、n2=100、n3=2
命名规则
- 由数字、字母、下划线组成,开头不能是数字。
- 不能是保留字和关键字。
- 区分大小写,不建议用大小写区分两个变量。
- 见名思意,变量用名词,方法用动词。
- 一般用驼峰式,特有名词根据私有性全大写或小写。
代码风格
- 每行结束不用写分号。
- 运算符左右建议各加一个空格。
- 推荐驼峰式命名。
- 左括号须紧接着语句不换行。
- 可用
go fmt
格式化文档统一风格
Go 语言基本数据类型
一、数据类型总体介绍
Go 语言数据类型分为基本数据类型和复合数据类型。
- 基本数据类型:整型、浮点型、布尔型、字符串。
- 复合数据类型:数组、切片、结构体、函数、map、通道 (channel)、接口等。
二、整型
分类
- 有符号整型:按长度分为 int8、int16、int32、int64,分别对应不同范围(如 int8 范围为 - 128 到 127),占用空间依次为 1、2、4、8 个字节。
- 无符号整型:对应有符号整型,为 uint8、uint16、uint32、uint64,范围从 0 开始(如 uint8 为 0 到 255),占用空间同对应有符号类型。
特殊整型
- uint:32 位系统上为 uint32,64 位系统上为 uint64;int:32 位系统上为 int32,64 位系统上为 int64;uintptr:无符号整型,用于存放指针。
- 注意:使用 int 和 uint 时需考虑平台差异,涉及二进制传输等场景避免使用。
相关操作
- 查看变量占用字节数:使用
unsafe.Sizeof(n1)
(需引入 unsafe 包)。 - 类型转换:不同长度整型可显式转换,如
num2 := int32(num1)
(num1 为 int8)。 - 数字字面量语法:Go1.13 后支持二进制(0b 前缀)、八进制(0o 前缀)、十六进制(0x 前缀)定义,可使用_分隔数字(如
v := 123_456
)。
- 查看变量占用字节数:使用
三、浮点型
- 类型:float32(最大范围约 3.4e38)和 float64(最大范围约 1.8e308),默认类型为 float64。
- 打印:使用
fmt.Printf
配合%f
(默认保留 6 位小数)或%.2f
(保留 2 位小数)等占位符。 - 精度问题:存在二进制浮点数精度丢失问题(如
8.2 - 3.8
结果为 4.399999999999999),可使用第三方包(如github.com/shopspring/decimal
)解决。 - 科学计数法:如
5.1234e2
(5.1234×10²)、5.1234E-2
(5.1234÷10²)。
四、布尔值
- 类型为 bool,值只有 true 和 false,默认值为 false。
- 注意:不允许将整型强制转换为布尔型,布尔型无法参与数值运算或与其他类型转换。
五、字符串
基本特性:以原生数据类型出现,内部使用 UTF-8 编码,值用双引号包裹,可包含非 ASCII 字符(如
s2 := "你好"
)。转义符:包括
\r
(回车)、\n
(换行)、\t
(制表符)、\'
(单引号)、\"
(双引号)、\\
(反斜杠)等。多行字符串:使用反引号(`)定义,换行原样保留,转义符无效。
常用操作
- 长度:
len(str)
。 - 拼接:
+
或fmt.Sprintf
。 - 分割:
strings.Split
。 - 包含判断:
strings.Contains
。 - 前缀 / 后缀判断:
strings.HasPrefix
/strings.HasSuffix
。 - 子串位置:
strings.Index
(从前往后)、strings.LastIndex
(从后往前)。 - 拼接切片:
strings.Join
。
- 长度:
六、byte 和 rune 类型
- byte:即 uint8,代表 ASCII 码字符。
- rune:即 int32,代表 UTF-8 字符,用于处理中文、日文等复合字符。
- 区别与应用:一个字母占 1 个字节(byte),一个汉字占 3 个字节;遍历字符串时,
for i := 0; i < len(s); i++
按 byte 遍历(可能乱码),for _, r := range s
按 rune 遍历(正确处理中文)。
七、修改字符串
需先转换为[]rune
(处理中文)或[]byte
(处理 ASCII),修改后再转回 string,转换会重新分配内存。例如:
s1 := "big"
byteS1 := []byte(s1)
byteS1[0] = 'p'
fmt.Println(string(byteS1)) // 输出"pig"
GoLang 基本数据类型转换
一、数据类型转换概述
Go 语言中只有强制类型转换,没有隐式类型转换。
二、数值类型之间的相互转换
- 包含类型:整型和浮点型。
- 转换规则:不同数值类型进行运算时,需转换为相同类型才能运行,例如
var a int8 = 20
,var b int16 = 40
,需将a
转换为int16
类型才能进行加法运算。 - 注意事项:建议从低位类型转换为高位类型,高位类型转换为低位类型可能会出现溢出,导致结果错误,如
var a int16 = 129
,转换为int8
类型后结果为-127
。 - 应用场景:在使用某些函数时,需将参数转换为函数要求的类型,如使用
math
包的Sqrt()
函数计算直角三角形斜边长时,需将int
类型的变量转换为float64
类型。
三、其他类型转换成 String 类型
- 使用
fmt.Sprintf
:需注意不同类型对应的格式,int
为%d
,float
为%f
,bool
为%t
,byte
为%c
。 - 使用
strconv
包int
转string
:使用strconv.Itoa
函数。float
转string
:使用strconv.FormatFloat
函数,需指定格式化类型、保留的小数位数等参数。bool
转string
:使用strconv.FormatBool
函数。int64
转string
:使用strconv.FormatInt
函数,需指定进制。
四、String 类型转换成数值类型
- 转换成
int
类型:使用strconv.ParseInt
函数,需指定字符串、进制和位数。 - 转换成
float
类型:使用strconv.ParseFloat
函数,需指定字符串和位数。 - 转换成
bool
类型:使用strconv.ParseBool
函数,不过实际意义不大。 - 转换成字符:可通过遍历字符串实现
五、特殊说明
在 Go 语言中,数值类型和bool
类型不能相互转换
GoLang 中的运算符
一、内置运算符类型
Golang 内置的运算符包括算术运算符、关系运算符、逻辑运算符、位运算符、赋值运算符。
二、算术运算符
- 常用运算符:包括加(+)、减(-)、乘(*)、除(/)、求余(%,公式为被除数 - (被除数 / 除数)* 除数)。
- 特殊说明:++(自增)和 --(自减)在 Go 语言中是单独的语句,并非运算符;且只能独立使用,没有前 ++ 和前 -- 的用法,例如
a = i++
和++i
都是错误的,正确写法是i++
。 - 除法特点:若运算数都是整数,结果会去掉小数部分,保留整数部分,如
10/3
结果为 3;若有浮点数参与,结果为浮点数,如10.0/3
结果约为 3.3333333333333335
短路特性:对于&&
,若左边操作数为 False,右边操作数不会执行;对于||
,若左边操作数为 True,右边操作数不会执行
Go 语言中的流程控制
一、流程控制概述
Go 语言中常用的流程控制有 if 和 for,switch 和 goto 主要用于简化代码、降低重复代码,属于扩展类流程控制
二、if else(分支结构)
- 基本写法:格式为
if 表达式1 {分支1} else if 表达式2 {分支2} else {分支3}
,当表达式 1 为 true 时执行分支 1,否则判断表达式 2,满足则执行分支 2,都不满足则执行分支 3。 - 注意事项:与 if 匹配的左括号
{
必须与 if 和表达式在同一行,与 else 匹配的{
必须与 else 在同一行,else 也必须与上一个 if 或 else if 右边的大括号在同一行。 - 特殊写法:可在 if 表达式前添加执行语句,再根据变量值判断,如
if score := 56; score >= 90 {…}
,其中变量作用域仅限于该 if 语句内。
三、for(循环结构)
- 基本格式:
for 初始语句;条件表达式;结束语句{循环体语句}
,条件表达式为 true 时循环,为 false 时退出。 - 变体形式
- 省略初始语句(需保留分号):如
i := 0; for ; i < 10; i++ {…}
。 - 省略初始语句和结束语句:类似 while 循环,如
i := 0; for i < 10 {…; i++}
。 - 无限循环:
for {循环体语句}
,可通过 break、goto 等强制退出。
- 省略初始语句(需保留分号):如
四、for range(键值循环)
可遍历数组、切片、字符串、map 及通道,返回值规律如下:
- 数组、切片、字符串返回索引和值。
- map 返回键和值。
- 通道只返回通道内的值。
例如遍历字符串:str := "abc 上海"; for index, val := range str {…}
。
五、switch case
- 基本用法:方便对大量值进行条件判断,每个 switch 只能有一个 default 分支。
- 特点:case 语句可不写 break,不会出现穿透现象;一个分支可包含多个值,用逗号分隔;也可在 switch 后不跟变量,直接在 case 中用表达式判断。
- fallthrough:可执行满足条件的 case 的下一个 case,默认穿透一层,如
case s == "a": fmt.Println("a"); fallthrough; case s == "b": fmt.Println("b")
会输出 a 和 b。
六、break(跳出循环)
- 作用场景:用于循环中跳出循环;在 switch 中执行一条 case 后跳出;多重循环中可通过标号 label 指定要跳出的循环。
- 示例:如
lable2: for i := 0; i < 2; i++ {for j := 0; j < 10; j++ {if j == 2 {break lable2}}}
。
七、continue(继续下次循环)
用于 for 循环内结束当前循环,开始下一次迭代;添加标签时,开始标签对应的循环。
八、goto(跳转到指定标签)
通过标签无条件跳转,可简化跳出循环等操作,如if n > 20 {goto label1}; ...; label1: ...
。
Golang 中的数组
一、数组介绍
数组是一系列同一类型数据的集合,每个数据称为数组元素,包含的元素个数为数组长度。在 Golang 中,数组是长度固定的数据类型,长度是类型的一部分,例如[5]int
和[10]int
是不同类型;数组元素占用连续内存地址,索引访问速度快。与数组对应的是 Slice(切片),切片更灵活,但理解数组是理解切片的基础。
二、数组定义
定义格式为var 数组变量名[元素数量]T
,其中元素数量必须是常量,且一旦定义长度不可变。例如var a [5]int
定义了一个长度为 5、元素类型为 int 的数组,[5]int
和[4]int
是不同类型,不能相互赋值。数组通过下标访问,下标从 0 开始,最后一个元素下标为len-1
,访问越界会触发 panic。
三、数组的初始化
- 方法一:使用初始化列表设置元素值,如
var numArray = [3]int{1, 2}
初始化后为[1 2 0]
,未指定的元素为对应类型零值。 - 方法二:让编译器根据初始值个数推断长度,用
...
代替长度,如var cityArray = [...]string{"北京", "上海", "深圳"}
,其类型为[3]string
。 - 方法三:指定索引值初始化,如
a := [...]int{1: 1, 3: 5}
,结果为[0 1 0 5]
,类型为[4]int
。
四、数组的遍历
- for 循环遍历:通过下标访问,如
for i := 0; i < len(a); i++ { fmt.Println(a[i]) }
。 - for range 遍历:返回索引和值,如
for index, value := range a { fmt.Println(index, value) }
。
五、数组是值类型
数组赋值和传参会复制整个数组,修改副本不会影响原数组。数组支持==
、!=
操作符,因内存总是被初始化。[n]*T
表示指针数组,*[n]T
表示数组指针。
六、多维数组
以二维数组为例,定义格式为var 数组变量名[元素数量][元素数量]T
,如a := [3][2]string{{"北京", "上海"}, {"广州", "深圳"}, {"成都", "重庆"}}
。遍历可使用嵌套 for range,如外层遍历获取每行,内层遍历获取每行元素。注意多维数组只有第一层可使用...
推导长度,内层不可。