1868 字
9 分钟
Go语言学习笔记(一)
学习目标:掌握Go语言,为K8s二次开发做准备
学习路线
基础语法
- 环境搭建
- 输入输出
- 变量类型
- 流程控制
- 循环
- 数组切片
- 映射map
- 函数
- 结构体
- 接口
- 错误处理
- 指针
实战应用
- JSON/YAML处理
- 文件操作
- 并发
- 包管理
- K8s插件开发
Go概念 -> K8s应用对照
fmt-> 调试输出Pod状态struct-> Pod/Service数据结构slice-> Pod列表管理map-> Labels/Annotations处理goroutine-> 并发处理多个Pod
环境搭建
Go环境配置步骤:
- 官网下载Go
- 设置环境变量
GOPROXY=https://goproxy.cn,direct(国内必须) - 初始化项目
go mod init project-name - 运行
go run main.go或go build
第一个程序:
package mainimport "fmt"func main() { fmt.Println("Hello K8s!")}常用命令:
go mod init k8s-tools- 创建模块go run main.go- 直接运行go build- 编译成可执行文件
输入输出
fmt包的三个主要函数:
fmt.Print()- 输出不换行fmt.Println()- 输出并换行fmt.Printf()- 格式化输出(重点)
package mainimport "fmt"
func main() { // 格式化输出 podName := "nginx-pod" replicas := 3 fmt.Printf("Pod名称: %s, 副本数: %d\n", podName, replicas)
// 读取输入 var name string var count int fmt.Print("请输入Pod名称: ") fmt.Scan(&name) // 注意&符号 fmt.Print("请输入副本数: ") fmt.Scan(&count)}常用格式化符号:
%s- 字符串%d- 整数%f- 浮点数%.1f- 保留1位小数%t- 布尔值%v- 任意类型
练习:写个简单的K8s工具
func main() { var podname string var replicas int
fmt.Print("请输入pod名称:") fmt.Scan(&podname) fmt.Print("请输入pod副本数:") fmt.Scan(&replicas)
fmt.Printf("准备创建pod:%s,副本数:%d\n", podname, replicas) fmt.Println("正在连接到 K8s 集群...")}变量和类型
Go基础数据类型:
string- 字符串,存储Pod名称、命名空间等int- 整数,存储副本数、端口号等float64- 浮点数,存储CPU/内存限制bool- 布尔值,存储Pod就绪状态等
变量声明的三种方式:
// 1. 完整声明var podName string = "nginx-pod"
// 2. 类型推断var serviceName = "my-service"
// 3. 简短声明 (函数内)deploymentName := "web-deployment"常量声明:
const ( DefaultNamespace = "default" MaxReplicas = 100)K8s Deployment示例:
func main() { deploymentName := "web-server" namespace := "production" replicas := 5 cpuLimit := 1.5 enabled := true
fmt.Printf(`=== K8s Deployment 信息 ===部署名称: %s命名空间: %s副本数量: %dCPU限制: %.1f核状态: %t`, deploymentName, namespace, replicas, cpuLimit, enabled)}注意:
:=只能在函数内使用- 声明的变量必须使用,否则编译错误
- 重新赋值用
=,不是:=
流程控制 if/else
if语句用来根据条件执行不同的代码分支,K8s开发中经常用到。
基本语法:
// 基础ifif podStatus == "Running" { fmt.Println("✅ Pod 状态正常")}
// if-elseif cpuUsage > 80.0 { fmt.Println("🔥 需要扩容")} else { fmt.Println("✅ CPU正常")}
// 多分支if podStatus == "Running" { fmt.Println("✅ 运行正常")} else if podStatus == "Pending" { fmt.Println("⚠️ 等待调度")} else if podStatus == "Failed" { fmt.Println("❌ 启动失败")} else { fmt.Println("❓ 未知状态")}比较运算符:
==等于!=不等于>>=大于(等于)<<=小于(等于)
逻辑运算符:
&&逻辑与 (都为true)||逻辑或 (至少一个true)!逻辑非 (取反)
Pod监控示例:
func main() { podName := "web-server-pod" status := "Running" cpuUsage := 75.5 memUsage := 60.2
fmt.Println("=== Pod监控报告 ===")
if status == "Running" { fmt.Println("✅ Pod运行正常") } else { fmt.Println("⚠️ Pod状态异常") }
if cpuUsage > 80 && memUsage > 85 { fmt.Println("⚠️ 资源使用率过高,建议扩容") } else { fmt.Println("✅ 资源使用正常") }}注意:
- 条件表达式结果必须是bool类型
- 大括号
{}必须有,左大括号必须在同一行 - 多分支从上到下检查,遇到true就执行并跳出
循环
循环用来重复执行代码,K8s开发中处理批量Pod、容器等数据时必不可少。
1. 传统for循环
// 基本语法: for 初始化; 条件; 更新 { }for i := 0; i < 3; i++ { fmt.Printf("第 %d 次重试连接...\n", i+1)}2. for range循环 (最常用)
// 遍历Pod列表pods := []string{"nginx-pod", "redis-pod", "mysql-pod"}
// 只要值for _, podName := range pods { fmt.Println(podName)}
// 要索引和值for i, podName := range pods { fmt.Printf("[%d] %s\n", i+1, podName)}3. 无限循环
for { // 监控Pod状态 if podReady { break // 退出条件 } time.Sleep(1 * time.Second)}4. 循环控制
// break - 跳出循环for _, pod := range pods { if pod == "target-pod" { fmt.Println("找到目标Pod") break }}
// continue - 跳过当前循环for _, pod := range pods { if pod == "skip-pod" { continue // 跳过这个pod } fmt.Println("处理:", pod)}集群健康检查练习:
func main() { services := []string{"web-service", "api-service", "db-service"} pods := [][]string{ {"web-1", "web-2", "web-3"}, {"api-1", "api-2"}, {"mysql-1", "mysql-2"}, } statuses := [][]string{ {"Running", "Running", "Failed"}, {"Running", "Pending"}, {"Running", "Running"}, }
// 嵌套循环遍历 for i, serviceName := range services { fmt.Printf("🔍 检查服务: %s\n", serviceName) servicePods := pods[i] serviceStatuses := statuses[i]
for j, podName := range servicePods { status := serviceStatuses[j] if status == "Running" { fmt.Printf(" ✅ %s: %s\n", podName, status) } else { fmt.Printf(" ❌ %s: %s\n", podName, status) } } }}数组和切片
切片是动态数组,K8s开发中管理Pod列表、容器列表必备。
数组 vs 切片
- 数组: 固定长度
[3]int{1,2,3},很少用 - 切片: 动态长度
[]int{1,2,3},常用
切片操作
// 创建切片pods := []string{"nginx-pod", "redis-pod"}pods = append(pods, "mysql-pod") // 添加元素
// 访问元素fmt.Println(pods[0]) // 第一个元素fmt.Println(len(pods)) // 长度
// 切片截取fmt.Println(pods[:2]) // 前2个: [nginx-pod redis-pod]fmt.Println(pods[1:]) // 从第2个开始: [redis-pod mysql-pod]
// 遍历for i, pod := range pods { fmt.Printf("[%d] %s\n", i, pod)}二维切片
// K8s多服务Pod管理services := []string{"web-service", "api-service"}pods := [][]string{ {"web-1", "web-2", "web-3"}, // web-service的Pod {"api-1", "api-2"}, // api-service的Pod}
// 访问: pods[服务索引][Pod索引]fmt.Println(pods[0]) // web-service的所有Podfmt.Println(pods[0][1]) // web-service的第2个Pod: web-2
// 遍历二维切片for i, serviceName := range services { fmt.Printf("服务: %s\n", serviceName) servicePods := pods[i] for j, podName := range servicePods { fmt.Printf(" [%d] %s\n", j+1, podName) }}Pod管理练习:
func main() { pods := []string{"web-pod-1", "db-pod-1"} pods = append(pods, "cache-pod-1", "api-pod-1", "worker-pod-1")
fmt.Println("=== K8s 集群状态 ===") fmt.Println("Pod 总数:", len(pods)) fmt.Println("Pod 列表:")
for i, podName := range pods { fmt.Printf(" [%d] %s\n", i+1, podName) }
fmt.Println("前3个Pod:", pods[:3]) fmt.Println("最后2个Pod:", pods[len(pods)-2:])}映射(map)
映射是键值对集合,用来处理K8s的Labels、Annotations、ConfigMap等。
基本语法
// 创建映射labels := map[string]string{ "app": "nginx", "version": "v1.0", "env": "production",}
// 访问值appName := labels["app"]
// 检查键是否存在version, exists := labels["version"]if exists { fmt.Println("版本:", version)}
// 添加/修改labels["tier"] = "frontend"
// 删除delete(labels, "version")
// 获取长度fmt.Println("标签数量:", len(labels))遍历映射
// 遍历键值对for key, value := range labels { fmt.Printf("%s = %s\n", key, value)}
// 只要键for key := range labels { fmt.Println("键:", key)}
// 只要值for _, value := range labels { fmt.Println("值:", value)}嵌套映射
// Pod标签管理: namespace -> podName -> labelspodLabels := map[string]map[string]string{ "default": { "web-pod": "app=nginx,version=v1.0", "cache-pod": "app=redis,version=v6.0", }, "production": { "api-pod": "app=api,version=v2.1", "db-pod": "app=mysql,version=v8.0", },}
// 安全访问嵌套映射if prodPods, exists := podLabels["production"]; exists { if apiLabels, exists := prodPods["api-pod"]; exists { fmt.Println("API Pod标签:", apiLabels) }}Labels管理练习:
func main() { podLabels := map[string]map[string]string{ "web-pod-1": {"app": "nginx", "version": "v1.0", "env": "prod"}, "web-pod-2": {"app": "nginx", "version": "v1.1", "env": "prod"}, "api-pod": {"app": "api", "version": "v2.0", "env": "staging"}, "db-pod": {"app": "mysql", "version": "v8.0", "env": "prod"}, }
// 统计环境分布 envCount := map[string]int{"prod": 0, "staging": 0} appCount := map[string]int{}
for podName, labels := range podLabels { fmt.Printf("📋 Pod: %s\n", podName)
for key, value := range labels { fmt.Printf(" %s = %s\n", key, value)
if key == "env" { envCount[value]++ } if key == "app" { appCount[value]++ } } }
fmt.Println("📊 统计:") fmt.Printf("- 生产环境Pod: %d\n", envCount["prod"]) fmt.Printf("- 应用分布: %v\n", appCount)注意:
- 映射遍历顺序是随机的
- 访问不存在的键会返回零值
- 必须先初始化才能使用:
make(map[string]string)
学习进度: 完成基础语法部分,接下来学习函数、结构体、错误处理等高级特性,最终实现K8s二次开发目标。