1868 字
9 分钟
Go语言学习笔记(一)

学习目标:掌握Go语言,为K8s二次开发做准备

学习路线#

基础语法

  • 环境搭建
  • 输入输出
  • 变量类型
  • 流程控制
  • 循环
  • 数组切片
  • 映射map
  • 函数
  • 结构体
  • 接口
  • 错误处理
  • 指针

实战应用

  • JSON/YAML处理
  • 文件操作
  • 并发
  • 包管理
  • K8s插件开发

Go概念 -> K8s应用对照#

  • fmt -> 调试输出Pod状态
  • struct -> Pod/Service数据结构
  • slice -> Pod列表管理
  • map -> Labels/Annotations处理
  • goroutine -> 并发处理多个Pod

环境搭建#

Go环境配置步骤:

  1. 官网下载Go
  2. 设置环境变量 GOPROXY=https://goproxy.cn,direct (国内必须)
  3. 初始化项目 go mod init project-name
  4. 运行 go run main.gogo build

第一个程序:

package main
import "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 main
import "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
副本数量: %d
CPU限制: %.1f
状态: %t`, deploymentName, namespace, replicas, cpuLimit, enabled)
}

注意:

  • := 只能在函数内使用
  • 声明的变量必须使用,否则编译错误
  • 重新赋值用 =,不是 :=

流程控制 if/else#

if语句用来根据条件执行不同的代码分支,K8s开发中经常用到。

基本语法:

// 基础if
if podStatus == "Running" {
fmt.Println("✅ Pod 状态正常")
}
// if-else
if 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的所有Pod
fmt.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 -> labels
podLabels := 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二次开发目标。

Go语言学习笔记(一)
https://dev-null-sec.github.io/posts/go语言k8s开发学习笔记/
作者
DevNull
发布于
2025-07-29
许可协议
CC BY-NC-SA 4.0