Java 开发者快速入门 Golang!超快速!

5 阅读9分钟

作为有 Java 基础的开发者,学习 Go 会非常快!因为两者都是静态强类型、编译型语言,但 Go 语法极简、无冗余设计,我会结合 Java 对比,从核心语法到特色特性,一步步详解 Go 所有关键语法,让你快速上手。


一、先搞懂:Java vs Go 核心差异

这是你快速入门的关键,先记住核心区别:

特性JavaGo
面向对象基于类、继承、封装、多态无类、无继承;用结构体 + 接口实现 OOP
异常处理try-catch-finally无异常,用 error 接口手动处理
循环for/while/do-while只有 for 循环(三合一)
并发线程(Thread)、线程池原生协程(goroutine) ,轻量高效
语法繁琐(分号、括号、类包裹)极简(无分号、无多余括号、类型后置)
函数必须依附类(方法)函数是一等公民,可独立存在、多返回值

二、环境准备 & 第一个程序

1. 环境安装

直接官网下载:Golang 官网:The Go Programming Language,安装后验证:

go version

2. Hello World(对比 Java)

Java 版

// 必须包裹在类中 
public class Hello { 
    public static void main(String[] args) { 
        System.out.println("Hello Go!"); 
    } 
}

Go 版

// 声明包名(main包=可执行程序,非库) 
package main 

// 导入依赖包(类似Java import) 
import "fmt" 

// 主函数:程序入口(无参数、无返回值,必须是main) 
func main() { 
    // 打印函数(类似System.out.println) 
    fmt.Println("Hello Go!") 
}

运行

go run main.go

核心语法点

  1. 包声明package main可执行程序的标识;其他包名是库包。
  2. 导入import 导入标准库 / 第三方库,多包导入用 () 包裹。
  3. 函数func 关键字定义函数,main 是唯一入口。
  4. 无分号:Go 自动补充分号,代码更简洁。

三、基础语法:变量 & 常量

Go 核心规则:类型后置(变量名在前,类型在后),零值初始化(声明未赋值会自动赋默认值)。

以下是 Go 中各种类型的零值速查表:

类型类别零值示例
数值类型0 / 0.0intfloat64int8 等均为 0 或 0.0
布尔类型falsebool 类型的零值为 false
字符串""空字符串
引用类型nil指针、切片、映射、通道、函数、接口
复合类型字段递归为零值数组和结构体的每个元素/字段都会被初始化为其类型的零值

1. 变量声明(4 种方式)

package main 

import "fmt" 

func main() { 
    // 方式1:标准声明(指定类型,零值初始化) 
    var age int // 默认值:0 
    var name string // 默认值:"" 
    fmt.Println(age, name) 
    
    // 方式2:声明+赋值(自动推导类型) 
    var score = 99.5 
    fmt.Println(score) 
    
    // 方式3:短变量声明(最常用!:= 自动推导类型,只能在函数内使用) 
    gender := "男" 
    fmt.Println(gender) 
    
    // 方式4:批量声明 
    var ( 
        a int = 10 
        b string = "test" 
    ) 
    fmt.Println(a, b) 
}

对比 Java

  • Java:int age = 18;(类型前置)
  • Go:age := 18var age int(类型后置,自动推导)
  • Go 无 null,零值:int=0/string=""/bool=false/指针=nil

2. 常量

const 定义,值不可修改,支持iota(枚举计数器):

package main 

import "fmt" 

// 普通常量 
const PI = 3.14159 

// iota:常量生成器(从0开始自动递增) 
const ( 
    SUN = iota // 0 
    MON // 1 
    TUE // 2 
) 

func main() { 
    fmt.Println(PI, SUN, MON) 
}

四、数据类型

Go 类型分基础类型复合类型,无包装类,一切皆值类型。

1. 基础类型

// 整型 
int int8 int16 int32 int64 // 有符号 
uint uint8 uint16 uint32 uint64 // 无符号 

// 浮点型 
float32 float64 

// 布尔型
bool // true/false 

// 字符串
string // 不可变,用双引号/反引号(反引号支持多行) 

// 字节/字符 
byte // uint8 别名(代表ASCII字符) 
rune // int32 别名(代表Unicode字符,处理中文)

2. 复合类型(重点)

(1)数组(固定长度,不常用)

// 声明:var 数组名 [长度]类型 
var arr [3]int = [3]int{1,2,3} 
// 短声明 
arr2 := [3]int{4,5,6}

(2)切片 Slice(Go 最核心数据结构,替代 Java List

切片是动态数组,长度可变,底层是数组,开发中 99% 用切片代替数组

package main 

import "fmt" 

func main() { 

    // 1. 声明切片(无长度,[]类型) 
    var s []int // 零值:nil 
    
    // 2. 初始化切片 
    s = []int{1,2,3} 
    
    // 3. make创建(指定长度、容量) 
    s2 := make([]int, 3, 5) // 长度3,容量5 
    
    // 4. 追加元素(append,自动扩容) 
    s = append(s, 4,5) fmt.Println(s) // [1 2 3 4 5] 
    
    // 5. 切片截取(类似Python) 
    sub := s[1:3] // 索引1~2(左闭右开) 
    fmt.Println(sub) // [2 3] 
}

(3)Map(替代 Java HashMap

键值对结构,键必须是可比较类型(int/string 等)。

package main 

import "fmt" 

func main() { 
    // 1. make创建map 
    m := make(map[string]int) 
    
    // 2. 赋值 
    m["张三"] = 18 m["李四"] = 20 
    
    // 3. 取值 
    age := m["张三"] 
    fmt.Println(age) 
    
    // 4. 判断键是否存在(ok-idiom,Go特色) 
    age, ok := m["王五"] 
    if !ok { 
        fmt.Println("键不存在") 
    } 
    
    // 5. 删除键 
    delete(m, "李四") 
}

(4)指针(比 Java 引用更简单)

Go 指针无指针运算,仅用于传递引用、修改原值,比 Java 更安全。

package main 

import "fmt" 

// 指针参数:修改原值(类似Java引用传递) 
func changeAge(p *int) { 
    *p = 20 // *指针:解引用,访问原值 
} 

func main() { 
    age := 18 
    // &变量:取地址 
    p := &age 
    fmt.Println(*p) // 18 
    
    changeAge(&age) 
    fmt.Println(age) // 20 
}

五、流程控制

Go 极简:if/for/switch 都无括号for 是唯一循环。

1. if 语句

支持初始化语句 + 条件判断(Go 特色),无括号:

age := 18 
// 标准if 
if age >= 18 { 
    fmt.Println("成年") 
} else { 
    fmt.Println("未成年") 
} 

// 带初始化的if(变量仅在if内有效) 
if num := 10; num > 5 { 
    fmt.Println("大于5") 
}

2. for 循环(三合一:替代 for/while/foreach)

(1)经典 for(类似 Java)

for i := 0; i < 5; i++ { 
    fmt.Println(i) 
}

(2)while 循环

i := 0 
for i < 5 { 
    fmt.Println(i) 
    i++ 
}

(3)无限循环

for {
	// 死循环,用break退出
}

(4)foreach(遍历切片 /map)

// 遍历切片
s := []int{1,2,3}
for index, value := range s {
	fmt.Println(index, value)
}

// 遍历map
m := map[string]int{"a":1}
for k, v := range m {
	fmt.Println(k, v)
}

3. switch 语句

无需 break(默认自动中断),支持多条件、任意类型、无表达式:

score := 90
switch score {
case 90, 100: // 多条件
	fmt.Println("优秀")
case 80:
	fmt.Println("良好")
default:
	fmt.Println("及格")
}

// 无表达式switch(替代if-else链)
switch {
case score >= 90:
	fmt.Println("A")
case score >= 80:
	fmt.Println("B")
}

4. defer 语句(Go 特色:延迟执行)

defer 修饰的代码,会在函数返回前执行,常用于关闭文件、释放锁、关闭连接(替代 Java finally)。

func main() {
	defer fmt.Println("最后执行")
	fmt.Println("先执行")
}
// 输出:先执行 → 最后执行

六、函数(Go 核心:一等公民)

Go 函数独立于结构体,支持多返回值、可变参数、匿名函数、闭包,这是 Java 没有的特性。

1. 标准函数

语法:func 函数名(参数) 返回值/返回值列表 { 代码 }

// 单返回值
func add(a int, b int) int {
	return a + b
}

// 多返回值(Go 特色!)
func calc(a int, b int) (int, int) {
	return a + b, a - b
}

2. 调用多返回值函数

sum, sub := calc(10, 5)
fmt.Println(sum, sub) // 15 5

// 忽略某个返回值(用下划线 _)
sum2, _ := calc(10, 5)

3. 可变参数(类似 Java 可变参)

// ...类型 表示可变参数
func sum(nums ...int) int {
	total := 0
	for _, num := range nums {
		total += num
	}
	return total
}

// 调用
sum(1,2,3) // 6

4. 匿名函数 & 闭包

// 匿名函数:直接赋值给变量
add := func(a, b int) int {
	return a + b
}
fmt.Println(add(1,2))

七、面向对象:结构体 & 方法(无类!)

Go 没有 class,用 struct(结构体)自定义类型,用方法绑定结构体,实现封装。

1. 定义结构体

// 定义结构体(类似 Java 类)
type Person struct {
	Name string
	Age  int
}

2. 初始化结构体

// 方式1
p1 := Person{Name: "张三", Age: 18}

// 方式2
var p2 Person
p2.Name = "李四"
p2.Age = 20

3. 方法(绑定结构体)

方法分值接收者(不修改原值)和指针接收者(修改原值)。

// 值接收者:只读,不修改结构体
func (p Person) sayHi() {
	fmt.Printf("我是%s,年龄%d\n", p.Name, p.Age)
}

// 指针接收者:修改结构体(必须用指针)
func (p *Person) setAge(age int) {
	p.Age = age
}

// 调用
func main() {
	p := Person{Name: "张三", Age: 18}
	p.sayHi()
	p.setAge(20)
	fmt.Println(p.Age) // 20
}

对比 Java

  • Java:class Person { void sayHi(){} }
  • Go:type Person struct {} + func (p Person) sayHi(){}

八、接口(Go 特色:隐式实现)

Go 接口无需显式声明实现(不用 implements),只要结构体拥有接口的所有方法,就自动实现该接口。

1. 定义接口

// 定义接口
type Animal interface {
	speak() string
}

2. 隐式实现接口

// 狗结构体
type Dog struct{}
// 实现接口方法(自动实现Animal接口)
func (d Dog) speak() string {
	return "汪汪汪"
}

// 猫结构体
type Cat struct{}
func (c Cat) speak() string {
	return "喵喵喵"
}

3. 使用接口

// 接口作为参数(多态)
func makeSound(a Animal) {
	fmt.Println(a.speak())
}

func main() {
	d := Dog{}
	c := Cat{}
	makeSound(d) // 汪汪汪
	makeSound(c) // 喵喵喵
}

对比 Java

  • Java:class Dog implements Animal
  • Go:无任何关键字,自动实现,解耦更强。

九、错误处理(无 try-catch)

Go 抛弃异常机制,用 error 接口手动处理错误,代码更清晰。

1. 标准错误处理

import "errors"

// 函数返回错误(多返回值:结果+error)
func divide(a, b int) (int, error) {
	if b == 0 {
		// 返回错误
		return 0, errors.New("除数不能为0")
	}
	return a / b, nil // nil=无错误
}

// 调用
func main() {
	res, err := divide(10, 0)
	if err != nil {
		// 处理错误
		fmt.Println("错误:", err)
		return
	}
	fmt.Println("结果:", res)
}

十、Go 并发:协程(goroutine)

Go 原生支持并发goroutine 是轻量级协程(比 Java 线程轻 1000 倍),无需线程池,直接用 go 关键字开启。

1. 开启协程

package main

import (
	"fmt"
	"time"
)

// 普通函数
func task() {
	for i := 0; i < 3; i++ {
		fmt.Println("任务执行:", i)
		time.Sleep(100 * time.Millisecond)
	}
}

func main() {
	// 开启协程(go + 函数调用)
	go task()

	// 主协程等待
	time.Sleep(1 * time.Second)
	fmt.Println("主程序结束")
}

2. Channel(通道:协程通信)

Go 原则:不要以共享内存通信,要以通信共享内存channel 用于协程间传递数据。

// 创建通道
ch := make(chan int)

// 协程发送数据
go func() {
	ch <- 10 // 发送
}()

// 主协程接收数据
num := <-ch
fmt.Println(num) // 10

十一、包管理 & 模块化

Go 1.11+ 用 Go Modules(替代 GOPATH),类似 Java Maven/Gradle。

1. 初始化模块

go mod init 项目名

2. 导入包规则

  • 首字母大写导出(public,外部可访问)
  • 首字母小写私有(private,仅包内可访问)
// 结构体大写:外部可访问
type User struct {
	Name string // 大写:导出
	age  int    // 小写:私有
}

总结(Java 转 Go 必背核心)

  1. 语法极简:类型后置、无分号、无多余括号、无类;
  2. 核心特色:函数多返回值、切片 slice、隐式接口、defer、goroutine 协程;
  3. OOP 替代:结构体 + 方法 + 接口,无继承;
  4. 错误处理:error 接口,无 try-catch;
  5. 并发:原生协程 + 通道,秒杀 Java 线程。