对比Java学习Go——程序结构与变量

程序基础结构

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。

入口函数

  • Java 的入口函数:显式的契约

    typescript 复制代码
    public 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 :这是一个参数,用于接收从命令行传递来的参数。
  • Go 的入口函数:隐式的约定

    go 复制代码
    package main // 1. 必须在main包中
    import "fmt"
    // 入口函数签名
    func main() {
        fmt.Println("Hello from Go")
    }
    • func :Go中声明函数的关键字。等价于Java的void someMethod()中的部分作用。
    • main :这是一个约定的函数名 。Go编译器会寻找名为 main 的函数作为入口。
    • () :表示函数没有参数。命令行参数不从这里传递。

第4章:基本数据类型与变量

类型系统

  • Java 的类型系统:原始类型与包装类的分裂

    • 原始类型 (Primitive Types)int, double, boolean, char, long, float, byte, short
    • 包装类 (Wrapper Classes)Integer, Double, Boolean, Character, Long, Float, Byte, Short
    • 装箱 (Boxing) :将原始类型 自动转换为对应的包装类对象
    • 拆箱 (Unboxing) :将包装类对象 自动转换为对应的原始类型
  • Go 的类型系统:统一的值类型

    • 只有值类型 :Go中的基本数据类型(如int, float64, bool, string)和结构体(struct)都是值类型
    • 存储方式 :变量直接存储 。当你声明一个int变量时,内存里就是一个实实在在的数字。
    • 赋值和传参默认是值拷贝 。将一个变量赋值给另一个变量,或者将其传递给函数,都会创建一份值的副本
    • 没有"包装"概念 :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 的值必须在编译时就能被确定,它不能是任何函数调用的返回值或运行时才能计算出的值。
    • 必须是基本类型:常量的值只能是数字(整数、浮点数)、布尔值、字符或字符串。不能是数组、切片、映射、结构体或函数。
    • 可组合性:常量表达式可以用于计算其他常量,因为它们都在编译期求值。
  • 强大的无类型常量(Untyped Constants)

    • 变量声明 :无类型常量没有明确的类型,它只有一种 "基本类型"integer, floating-point, string, boolean)。
    • 影视转换:它可以在上下文中根据需要被隐式转换为合适的类型,只要不造成精度丢失。
相关推荐
AntBlack4 小时前
每周学点 AI:ComfyUI + Modal 的一键部署脚本
人工智能·后端·aigc
5大大大大雄5 小时前
docker容器日志处理
后端
我是哪吒5 小时前
分布式微服务系统架构第170集:Kafka消费者并发-多节点消费-可扩展性
后端·面试·github
Badman6 小时前
分布式系统下的数据一致性-Redis分布式锁
redis·分布式·后端
Java水解6 小时前
盘点那些自带高级算法的SQL
后端
一只叫煤球的猫7 小时前
2025年基于Java21的的秒杀系统要怎么设计?来点干货
后端·面试·性能优化
方圆想当图灵7 小时前
《生产微服务》评估清单 CheckList
后端·微服务
服务端技术栈7 小时前
历时 1 个多月,我的第一个微信小程序「图片转 Excel」终于上线了!
前端·后端·微信小程序
计算机毕业设计指导7 小时前
基于Spring Boot的幼儿园管理系统
spring boot·后端·信息可视化