Go语言是谷歌推出的静态强类型、编译型、极简高效、原生并发的后端编程语言,主打语法简洁、编译快速、高性能、高并发。相较于Java、JavaScript,Go剔除了冗余语法、简化了编程模型,同时保留了静态类型的安全性。
基础语法是Go语言开发的核心基石,包含变量与常量、基本数据类型、运算符、流程控制、指针、类型别名六大核心模块,是Go工程开发、笔试面试、进阶学习的必备基础。本文沿用统一学术体系,逐层拆解原理、语法规范、易错坑点,搭配实战代码与嵌入式面试真题,实现理论与刷题一体化掌握。
一、变量与常量
Go是强类型语言,所有变量必须先声明、后使用,类型固定不可随意变更。Go严格禁止无效代码,定义的变量、常量必须使用,否则编译报错。
1.1 变量声明规则
Go提供四种变量声明方式,适配全局、函数内不同场景,支持类型显性声明与自动推导。
package main
import "fmt"
// 1. 标准声明:指定类型,默认零值
var name string
var age int
// 2. 声明并初始化,显性赋值
var height int = 180
// 3. 类型推导:省略类型,编译器自动推导
var weight = 72.5
func main() {
// 4. 短变量声明:函数内专属,最常用
addr := "Beijing"
fmt.Println(name, age, height, weight, addr)
}
1.2 核心特性
- 零值机制:Go变量声明后自动赋予默认零值,无未定义变量,规避野指针、空值异常;
- 强制使用:声明的变量必须被使用,否则编译失败,杜绝冗余代码;
- 短变量限制:
:=仅能在函数内部使用,全局变量必须用var声明; - 多变量声明:支持批量声明多个同类型或推导类型变量。
1.3 常量与iota枚举
常量使用const 定义,编译期确定值,运行期不可修改,常用于定义固定配置、状态码、枚举值。
// 单个常量
const PI = 3.1415926
// 批量常量
const (
OK = 200
ERROR = 500
)
// iota 常量计数器(Go专属)
// iota从0开始,逐行自增1,实现批量枚举
const (
Monday = iota // 0
Tuesday // 1
Wednesday // 2
)
iota核心特性:仅在const代码块内生效,初始值为0,每新增一行常量定义自动+1,可快速实现枚举序列。
本节面试真题
题目:简述Go变量零值机制和短变量声明的限制
答案:Go变量声明后自动赋予对应类型零值,无未初始化变量;短变量声明 := 只能用于函数内部,全局变量不支持,且会自动推导类型。
二、基本数据类型
Go数据类型分为基本类型和复合类型,基本类型是最基础的数据载体,具备固定字节数、跨平台统一特性,规避了C语言类型字节混乱问题。
2.1 八大基本数据类型
2.1.1 整型(有符号/无符号)
有符号整型:int8、int16、int32、int64
无符号整型:uint8、uint16、uint32、uint64
通用整型:int、uint(适配系统位数,32/64位自动适配)
2.1.2 浮点型
float32(单精度)、float64(双精度,默认浮点类型)
2.1.3 布尔型
bool,仅两个值:true、false,不参与数值运算、不与数字互转(区别于C/Java)。
2.1.4 字符串型
string,原生支持字符串,默认UTF-8编码,字符串不可变。
2.1.5 字符类型
byte(uint8别名,存储ASCII字符)、rune(int32别名,存储Unicode/中文)
2.2 类型核心规则
- 强类型严格校验:不同类型变量无法直接运算,必须手动强制转换;
- 字符串不可变:无法直接修改字符串单个字符,需转为切片操作;
- 布尔独立:bool类型不能和0/1、数字进行等价判断;
- 零值统一:数值类型0、字符串空串、布尔false、指针nil。
本节面试真题
题目:byte和rune的区别?
答案:byte对应uint8,用于存储单字节ASCII字符;rune对应int32,用于存储多字节Unicode字符(中文、特殊符号),是Go处理中文的核心类型。
三、运算符
Go运算符体系简洁,剔除了冗余、不安全语法,整体分类与主流语言一致,但存在多处独有规则与禁忌。
3.1 常用运算符分类
算术运算符:+、-、*、/、%、++、--
赋值运算符:=、+=、-=、*=、/=、%=
比较运算符:==、!=、>、<、>=、<=
逻辑运算符:&&、||、!
位运算符:&、|、^、<<、>>
3.2 Go独有严格规则(高频考点)
- 自增自减只能后置:仅支持
i++、i--,禁止++i、--i; - 自增自减不是表达式:不能参与运算、赋值、判断,只能单独语句;
- 三元运算符删除:Go 无三元表达式,所有分支判断只能用if-else;
- 逻辑短路规则不变:
&&遇false短路,||遇true短路。
本节面试真题
题目:Go为什么没有三元运算符?
答案:Go设计理念为语法极简、可读性优先,三元运算符易写出嵌套晦涩代码,统一用if-else替代,保证代码风格统一、易维护。
四、流程控制
Go大幅简化了流程控制语法,剔除冗余格式,强制规范代码风格,核心包含if分支、switch分支、for循环三大结构,无while、do-while循环。
4.1 if 分支结构
核心特性:条件括号可省略,大括号必须保留,禁止单行省略大括号,强制代码规范。
func main() {
score := 85
if score >= 80 {
fmt.Println("良好")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("不及格")
}
}
支持前置语句:if语句内可前置定义变量,变量作用域仅当前分支。
if num := 10; num > 5 {
fmt.Println("大于5")
}
4.2 switch 分支结构(Go特色)
区别于Java/C,Go switch默认自动break,匹配成功后自动终止,无需手动写break,杜绝穿透问题。
func main() {
week := 2
switch week {
case 1:
fmt.Println("周一")
case 2:
fmt.Println("周二")
default:
fmt.Println("未知")
}
}
进阶特性:支持无表达式switch(替代if-else多分支)、多值匹配、穿透语法(fallthrough)。
4.3 for 循环(唯一循环结构)
Go 舍弃 while、do-while,仅保留 for 循环,通过变形实现所有循环场景。
// 1. 标准for循环
for i := 0; i < 5; i++ {
fmt.Println(i)
}
// 2. 等效while循环
i := 0
for i < 5 {
i++
}
// 3. 无限循环
for {
// 死循环,搭配break终止
}
4.4 跳转语句
break:终止当前循环/switch;continue:跳过本次循环;支持标签跳转,适配多层循环跳出场景。
本节面试真题
题目:Go的switch和其他语言switch最大区别?
答案:Go switch默认自动break,不会穿透;如需穿透必须手动使用fallthrough关键字,语法更安全、规避经典bug。
五、指针(Go核心重难点)
指针是Go语言的核心特性,相较于C语言,Go指针安全简洁、无指针运算,既保留了内存操作、传址修改的优势,又规避了野指针、内存越界问题,是参数修改、性能优化、底层开发的基础。
5.1 指针核心概念
变量:存储具体数值,占用内存空间;
指针变量:存储变量的内存地址;
&:取地址符号;*:解引用符号(取地址对应的值)。
5.2 基础语法演示
func main() {
a := 10
// &取值地址
p := &a
fmt.Println("变量值:", a)
fmt.Println("内存地址:", p)
// *解引用,修改原变量值
*p = 20
fmt.Println("修改后:", a)
}
5.3 指针核心作用
- 方法传参修改原值:普通传参是值拷贝,指针传参直接操作原变量内存;
- 减少内存拷贝:大结构体、大数据传参用指针,提升性能;
- 实现共享数据:多个指针指向同一内存,实现数据共享。
5.4 Go指针严格限制
- 禁止指针运算:不支持指针++、指针偏移,彻底杜绝内存越界;
- 空指针nil:未初始化指针默认值为nil,不能直接解引用;
- 类型匹配:指针类型必须与原变量类型一致,禁止随意转换。
本节面试真题
题目:Go指针和C语言指针的区别?
答案:Go指针无指针运算,不支持偏移、加减,安全无内存越界;C语言指针可运算、自由度高但风险大。Go保留指针传址优势,舍弃不安全特性。
六、类型别名
Go支持自定义类型别名,用于简化长类型、语义化定义类型、适配框架封装,分为类型别名和自定义新类型两种,二者极易混淆。
6.1 类型别名(type =)
使用 type 别名 = 原类型 定义,别名与原类型完全等价、类型互通,只是语法简写。
// 类型别名
type MyInt = int
func main() {
var a MyInt = 10
var b int = a // 完全兼容,无转换报错
fmt.Println(a, b)
}
6.2 自定义新类型(无=)
使用 type 新类型 原类型 定义,创建全新独立类型,与原类型不互通,需手动转换。
// 自定义新类型
type Age int
func main() {
var a Age = 18
var b int = a // 编译报错,类型不匹配
}
6.3 核心应用场景
- 简化复杂长类型(函数类型、结构体指针类型);
- 语义化区分业务类型,提升代码可读性;
- 框架封装中统一类型管理,适配多版本兼容。
本节面试真题
题目:类型别名和自定义新类型的区别?
答案:带=是类型别名,与原类型完全等价、互通;不带=是全新自定义类型,与原类型相互独立、不兼容,需要手动类型转换。
七、全文终极背诵总结
1、变量常量:Go变量零值初始化、强制使用,短变量仅函数内可用;const定义常量,iota实现批量枚举自增;
2、数据类型:静态强类型,不同类型不可直接运算;byte存ASCII、rune存Unicode,字符串不可变;
3、运算符:无三元运算符,自增自减仅后置、不可参与运算,语法极简安全;
4、流程控制:仅for一种循环,switch默认break、无穿透,if强制大括号,代码风格统一;
5、指针:无指针运算,安全高效,用于传参改值、减少拷贝,杜绝内存越界风险;
6、类型别名:=代表别名互通,无=代表新类型独立,常用于代码简化与业务语义化。