1. 包、入口、main
go
package main // main包,可执行程序
import "fmt" //导入包
func main() { //程序入口,无参数无返回
fmt.Println("hello go")
}
package main:生成可执行文件;其他包是库。- main函数不能传参、没有返回值。
编译运行:
bash
go run main.go
go build -o app main.go
2. 变量、常量
go
// 声明
var a int
var b int = 10
c := 20 //短变量,只能函数内部使用,自动推导类型
//多变量
var x,y int = 1,2
//常量
const pi = 3.14
:=不能写在函数外面。
类型:int int64 string bool float64
3. 基本类型转换
Go不隐式转换,必须显式转换
go
var a int = 10
var b int64 = int64(a)
string和数字转换用 strconv 包。
4. if for (没有while)
go
// if,条件不用括号
if a > 10 {
} else if a <5 {
}else{
}
// for,唯一循环
for i:=0;i<5;i++{
fmt.Println(i)
}
// 等价while
for a>0 {
a--
}
// range遍历数组、slice、map
arr := []int{11,22,33}
for idx,val := range arr {
fmt.Println(idx,val)
}
5. 函数
go
func add(a int,b int) int{
return a+b
}
//多返回值(Go高频,经常返回(结果,err))
func div(a,b int) (int,error){
if b ==0{
return 0,fmt.Errorf("div zero")
}
return a/b,nil
}
调用:
go
res,err := div(10,0)
if err != nil {
//处理错误
}
Go没有异常机制,用error返回错误,不抛异常。
6. slice切片(最常用,动态数组)
go
//初始化
s := []int{1,2,3}
s2 := make([]int,0,10) //长度0,容量10
//追加
s = append(s,4)
//切片截取 s[low:high]
sub := s[1:3]
slice底层共享数组,修改会互相影响。
7. map
go
//map必须make初始化,直接var声明是nil,不能存数据
m := make(map[string]int)
m["a"] = 10
//读取,ok判断key是否存在
val,ok := m["b"]
if ok {
fmt.Println(val)
}
delete(m,"a") //删除key
8. struct结构体
go
type User struct {
Name string
Age int
}
func main(){
u := User{Name:"zhangsan",Age:20}
fmt.Println(u.Name)
}
方法(绑定struct)
go
func (u *User) SetAge(age int){ //指针接收者,修改结构体
u.Age = age
}
指针接收者:需要修改结构体内容;值接收者只拷贝只读。
9. 指针
*取值,&取地址
go
a := 10
p := &a
fmt.Println(*p)
10. 并发:goroutine + channel(Go灵魂,面试必问)
goroutine:轻量级协程,go关键字启动
go
func hello(){
fmt.Println("goroutine")
}
func main(){
go hello() //开启协程
time.Sleep(time.Second)
}
channel协程通信:
go
ch := make(chan int)
go func(){
ch <- 100 //写channel
}()
v := <- ch //读channel
fmt.Println(v)
11. defer 延迟执行
函数退出前执行,常用于关闭文件、关闭资源
go
func test(){
f,err := os.Open("test.txt")
if err!=nil{
return
}
defer f.Close() //函数返回前自动关闭
}
12. 错误处理核心考点
- Go没有try‑catch;
- 函数多返回值,把error作为返回;
nil代表无错误;fmt.Errorf("xxx")构造错误。
面试简答高频问题
-
slice和array区别?
array长度固定;slice是动态切片,底层指向数组。make创建slice。
-
map为什么一定要make?
var得到nil map,未初始化,写入直接panic。
-
goroutine和线程区别?
goroutine用户态轻量级,栈小,go调度器管理;OS线程内核态,开销大。
-
defer执行时机?
当前函数return之前执行。
-
值接收者 vs 指针接收者?
指针:修改原结构体,拷贝小;值接收者拷贝一份副本。
一段极简完整示例(读取文件)
go
package main
import (
"fmt"
"os"
)
func main() {
data, err := os.ReadFile("/etc/hosts")
if err != nil {
fmt.Println("read err:", err)
return
}
fmt.Println(string(data))
}