程序基础结构
Hello, World!
程序对比
-
Java 的
HelloWorld.java
java// 1. 声明这个类所在的包(目录结构) package com.example; // 2. 导入需要使用的类 import java.lang.System; // 3. 定义一个公共类,类名必须与文件名完全一致 public class HelloWorld { // 4. 定义一个公开、静态、无返回值的主方法 // 这是JVM规定的程序入口点 public static void main(String[] args) { // 5. 调用系统类的静态方法`out.println`来打印字符串 System.out.println("Hello, World!"); } }
-
包声明 (Package Declaration) :定义了类所在的命名空间,通常与文件目录结构对应,主要用于避免类名冲突。
-
导入语句 (Import Statement) :引入其他包中的类,以便在当前类中使用。
java.lang
包(包含System
类)会被自动导入。 -
类定义 (Class Definition) :Java是纯粹的面向对象语言,所有代码都必须位于类内部,文件名必须与公共类的类名完全一致。
-
主方法 (Main Method) :这是JVM寻找程序开始执行的唯一入口点,方法签名必须一字不差。
public:方法需要被JVM访问到。
static:方法在类加载时就可调用,无需创建类的实例。
void:方法不返回任何值。
String[] args:用于接收命令行参数。
-
执行语句 :通过
类.静态字段.方法()
的长链式调用完成输出。
-
-
Go 的
hello.go
go// 1. 声明该文件属于哪个包 // 'main'包是一个特殊的包,它表示这是一个可执行程序 package main // 2. 导入一个标准库包,用于格式化输出 import "fmt" // 3. 定义一个函数 main。 // 它是程序的入口点,没有参数,没有返回值。 func main() { // 4. 调用 fmt 包的 Println 函数来打印字符串 fmt.Println("Hello, World!") }
-
包声明 (Package Declaration) :同样定义了代码所属的包。包名不一定与目录名相同,但良好实践是保持一致。
特殊性 :
main
包是特殊的。它告诉Go编译器,这个包应该被编译成一个可执行程序,而不是一个库。 -
导入语句 (Import Statement) :引入标准库中的
fmt
包(格式化IO),所有导入必须被使用,否则编译报错。 -
函数定义 (Function Definition) :
main
函数是Go程序的入口点 。它属于main
包。没有访问修饰符(
public
),因为Go使用字母大小写来控制可见性(大写字母开头表示导出,小写则包内私有)。没有
static
关键字,因为Go没有类的概念,所有函数都是"独立"的。没有参数(
String[] args
),命令行参数通过os.Args
变量获取。 -
执行语句 :通过
包名.函数名()
的直接调用完成输出,更简洁。
-
代码组织
-
Java 的
package
:作为命名空间的类容器- 强制映射 :包名必须与文件系统中的目录路径完全匹配,这是Java语言的强制要求。
- 文件内容 :该文件必须 以包声明开头,并且只能包含一个与该文件同名的公共类。
- 访问控制(可见性) :Java的访问控制是基于类的,使用关键字修饰类、方法或字段。
-
Go 的
package
:作为构建单元的代码集合- 松散映射 :一个目录下的所有Go文件必须属于同一个包 。包名建议与目录名相同,但不是强制要求 (除非是
main
包)。 - 文件内容 :一个目录下可以有多个
.go
文件,它们共同组成一个包。文件内容没有类名限制。
- 访问控制(可见性) :首字母大写的标识符表示public,首字母小写的标识符标识private。
- 松散映射 :一个目录下的所有Go文件必须属于同一个包 。包名建议与目录名相同,但不是强制要求 (除非是
入口函数
-
Java 的入口函数:显式的契约
typescriptpublic class HelloWorld { // 入口函数签名 public static void main(String[] args) { System.out.println("Hello from Java"); } }
- public :JVM需要能够调用这个方法作为程序的起点,如果一个方法不是
public
的,它就无法被JVM这个"外部"调用者访问到。 - static :JVM在启动时,并没有 创建任何类的实例,
static
关键字表示这个方法是属于类本身的,而不是属于某个对象。 - void :它向JVM表明,这个入口方法执行完成后不返回任何值 给调用者(即操作系统),这是一个返回值类型声明。
- main :这是一个约定俗成的方法名 ,JVM会固定寻找名为
main
的方法作为入口。 - String[] args :这是一个参数,用于接收从命令行传递来的参数。
- public :JVM需要能够调用这个方法作为程序的起点,如果一个方法不是
-
Go 的入口函数:隐式的约定
gopackage main // 1. 必须在main包中 import "fmt" // 入口函数签名 func main() { fmt.Println("Hello from Go") }
- func :Go中声明函数的关键字。等价于Java的
void someMethod()
中的部分作用。 - main :这是一个约定的函数名 。Go编译器会寻找名为
main
的函数作为入口。 - () :表示函数没有参数。命令行参数不从这里传递。
- func :Go中声明函数的关键字。等价于Java的
第4章:基本数据类型与变量
类型系统
-
Java 的类型系统:原始类型与包装类的分裂
- 原始类型 (Primitive Types) :
int
,double
,boolean
,char
,long
,float
,byte
,short
。 - 包装类 (Wrapper Classes) :
Integer
,Double
,Boolean
,Character
,Long
,Float
,Byte
,Short
。 - 装箱 (Boxing) :将原始类型 自动转换为对应的包装类对象。
- 拆箱 (Unboxing) :将包装类对象 自动转换为对应的原始类型。
- 原始类型 (Primitive Types) :
-
Go 的类型系统:统一的值类型
- 只有值类型 :Go中的基本数据类型(如
int
,float64
,bool
,string
)和结构体(struct
)都是值类型。 - 存储方式 :变量直接存储值 。当你声明一个
int
变量时,内存里就是一个实实在在的数字。 - 赋值和传参 :默认是值拷贝 。将一个变量赋值给另一个变量,或者将其传递给函数,都会创建一份值的副本。
- 没有"包装"概念 :Go的基本类型就是它们本身,它们不需要也不可以被"包装"成对象来放入集合。
- 只有值类型 :Go中的基本数据类型(如
变量声明
-
方式一:标准显式声明
var
go// 语法:var <变量名> <类型> [= 初始值] var i int = 10 var s string = "Hello" const Pi float64 = 3.14 // 常量声明
- 关键字顺序 :使用了
var
这个关键字开头,然后是变量名,最后才是类型(var i int
)。 - 类型后置:类型写在变量名之后。这是Go的一个显著特征,在函数声明等地方也会看到这种模式。
- 常量 :使用
const
关键字声明常量。 - 分号 :行尾的分号
;
在Go中是可选的,编译器会自动添加。通常我们都不写。
- 使用场景:当你需要显式地指定一个与初始化值类型不同的类型,或者稍后才赋值时,使用这种方式。
- 关键字顺序 :使用了
-
方式二:短变量声明
:=
(最常用)- 类型推断 :编译器会根据等号右侧的初始值自动推断 出变量的类型,
10
是 untyped integer constant,所以i
被推断为int
。 - 使用场景 :在函数内部 声明并初始化一个局部变量时,绝大多数情况都使用
:=
。
- 类型推断 :编译器会根据等号右侧的初始值自动推断 出变量的类型,
-
方式三:隐式类型声明(省略类型) :当使用
var
声明并初始化时,如果初始值能明确推断出类型,可以省略类型。 -
Go变量声明特性
- := 不是动态类型 :
i := 10
之后,变量i
就被永久地、静态地 确定为int
类型,Go依然是静态强类型语言。 - :=是声明,不是赋值 :
:=
操作符左侧必须至少有一个新的、未被声明过的变量。 - 零值机制 :在Go中,使用
var
声明但未显式初始化的变量会被自动初始化为其类型的**零值,:=
必须附带初始化值。
- := 不是动态类型 :
-
核心差异对比
特性 Java: int i = 10;
Go: var i int = 10
Go: i := 10
语法关键字 类型关键字 ( int
)var
:=
类型位置 类型前置 类型后置 类型被推断,隐式 类型要求 必须显式写出 可显式写出,也可省略 完全由编译器推断 主要作用域 任何作用域 任何作用域 仅限于函数内部 可读性 非常明确,但稍显冗长 明确,略显冗长 极其简洁 哲学体现 严谨、明确、减少歧义 灵活性、兼容性 简洁、高效、开发体验好
常量定义:final
vs const
-
Java 的常量:
final
关键字- 语法与基本用法 :
final
关键字用于修饰变量,表示该变量只能被赋值一次。 - 运行时常量 :
final
变量的值是在运行时 确定的。你可以在构造函数或静态初始化块中计算一个值并赋给final
变量。 - 应用范围广 :
final
可以修饰局部变量、成员变量(实例字段)、静态变量(类字段)和方法参数。 - 不要求编译期确定 :一个
final
变量的初始值可以是一个方法调用的返回值或一个非常量表达式,只要保证只赋值一次即可。
- 语法与基本用法 :
-
Go 的常量:
const
关键字- 语法与基本语法 :Go 使用专门的
const
关键字来声明常量,其设计非常严格且目的明确:定义编译期可知的值。 - 编译期常量 :
const
的值必须在编译时就能被确定,它不能是任何函数调用的返回值或运行时才能计算出的值。 - 必须是基本类型:常量的值只能是数字(整数、浮点数)、布尔值、字符或字符串。不能是数组、切片、映射、结构体或函数。
- 可组合性:常量表达式可以用于计算其他常量,因为它们都在编译期求值。
- 语法与基本语法 :Go 使用专门的
-
强大的无类型常量(Untyped Constants)
- 变量声明 :无类型常量没有明确的类型,它只有一种 "基本类型" (
integer
,floating-point
,string
,boolean
)。 - 影视转换:它可以在上下文中根据需要被隐式转换为合适的类型,只要不造成精度丢失。
- 变量声明 :无类型常量没有明确的类型,它只有一种 "基本类型" (