Java程序员学Go语言指南(上篇)_java程序员入门书籍
环境配置篇:从JDK到GoRoot
1. 安装对比
- Java:安装JDK → 配置JAVA_HOME → javac验证
- Go:官网下载.msi → 自动设置GOROOT → go version验证
2. VS Code配置差异
# Java环境
安装Extension Pack for Java
需要配置Maven路径
# Go环境
安装Go扩展(Go Team at Google)
自动安装gopls等工具链
3. 项目初始化实战
// Java项目结构(Maven)
src/
main/
java/
com/example/
Main.java
pom.xml
// Go项目结构
go.mod // 类似pom.xml
main.go
└── utils/ // 自定义包
└── math.go
基础语法篇:当Java遇上Go
1. 变量声明对照表
场景 | Java写法 | Go写法 | 核心差异 |
显式声明 | int count = 10; | var count int = 10 | 类型后置 |
类型推断 | var list = new ArrayList<>() | list := []string{} | 短变量声明 |
多变量声明 | 不支持 | a, b := 1, "hello" | 元组式赋值 |
2. 数组与切片(关键差异点)
// Java数组 vs ArrayList
int[] arr = {1,2,3}; // 定长
ArrayList list = new ArrayList<>(); // 动态扩容
list.add(4);
// Go数组 vs 切片
arr := [3]int{1,2,3} // 定长数组
slice := []int{1,2,3} // 动态切片
slice = append(slice, 4) // 扩容需重新赋值
// 内存细节:切片底层引用数组
header := slice[:2] // 创建新切片头(共享底层数组)
3. 流程控制对比
循环结构:
// Java三剑客
for (int i=0; i<5; i++) { /*...*/ }
while(condition) { /*...*/ }
do { /*...*/ } while(condition);
// Go的万能for
for i := 0; i < 5; i++ { /* 传统循环 */ }
for condition { /* while替代 */ }
for { /* 无限循环 */ break }
Switch陷阱:
// Java需要break
switch (x) {
case 1:
System.out.println("one");
break; // 必须显式阻断
default:
System.out.println("other");
}
// Go默认不穿透
switch x {
case 1:
fmt.Println("one") // 自动break
case 2,3: // 多值匹配
fmt.Println("two or three")
default:
fmt.Println("other")
}
函数篇:从方法到一等公民
1. 基础函数差异
// Java方法
public static int add(int a, int b) {
return a + b;
}
// 单返回值
// 必须属于某个类
// Go函数
func add(a, b int) int {
return a + b
}
// 独立存在
// 支持多返回值
2. 多返回值革命
// 文件读取的典型模式
func readFile(path string) ([]byte, error) {
content, err := os.ReadFile(path)
return content, err
}
// 调用时显式处理错误
data, err := readFile("test.txt")
if err != nil {
log.Fatal(err)
}
3. 函数式编程初探
// Java Lambda
List nums = Arrays.asList(1,2,3);
nums.stream()
.map(x -> x * 2)
.forEach(System.out::println);
// Go匿名函数
nums := []int{1, 2, 3}
// 立即执行函数
func() {
fmt.Println("立即执行!")
}()
// 函数作为参数
transform := func(x int) int { return x * 2 }
for _, n := range nums {
fmt.Println(transform(n))
}
避坑指南:Java转Go常见错误
- 分号依赖:Go编译器自动加分号,行尾不能随意换行
// 错误写法
return
result // 实际返回的是空值
// 正确写法
return result
- 作用域误解:
if num := 10; num > 5 {
fmt.Println(num) // 正确
}
fmt.Println(num) // 编译错误!num只在if块内有效
- 值传递陷阱:
func updateSlice(s []int) {
s[0] = 9 // 修改底层数组
s = append(s, 4) // 创建新切片
}
// 调用者看到的切片长度不变!
上篇实战作业
- 将Java版冒泡排序改写为Go实现
- 实现一个多返回值函数:计算圆面积和周长
- 用Go重写Java工具类中的字符串处理方法
(提示:Go标准库常用包 - strings, strconv, math)
下篇预告:中篇将深入Go的"结构体+接口"面向对象模型,揭秘defer的黑魔法,并对比Go Module与Maven的依赖管理哲学。