1.变量声明
- Java
int num = 0;
Integer num = 0;
Integer num = new Integer(0);
String str = "";
String str = new String("");
- Go
var num int
var num int = 0
num := 0
var str string = ""
str := ""
2.常量定义
-
Java
Java直接.这个枚举输出的是这个枚举的名字
-
Go
常量的定义其实和Java没有什么不同,都是一个.go文件(类文件)通过 . 的方式进行访问
Go的常量定义要是想让外部包访问,就必须让首字母大写,比如大写的A、B能访问,但是小写的c不能在常量包外访问
3.集合与切片
- Java 集合 -> 动态数组
int[] nums = new int[10]; // 数组
List<Integer> list = new ArrayList<>(); // 集合
- Go 切片 -> 动态数组
var nums = [2]int{} // 数组
var nums = make([]int,0) // 切片 nums := make([]int,0)
nums := make([]int,0)
nums := []int{}
4.Map哈希表
- Java
Map<String,String> map = new HashMap<>();
map.put("tmp","tmp");
// 如何遍历 1.遍历Entry 2.遍历key,通过key去map拿
for (Map.Entry<String, String> entry : map.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
System.out.println("Key: " + key + ", Value: " + value);
}
for (String key : map.keySet()) {
System.out.println("Key: " + map.get(key));
}
- Go
var myMap = map[string]string
myMap := make(map[string]string)
myMap["tmp"] = "tmp"
// 如何遍历 for...range即可
for key, value := range myMap {
fmt.Printf("Key: %s, Value: %d\n", key, value)
}
// 也可以采用匿名变量的方法
for key := range myMap {
fmt.Printf("Key: %s\n", key)
}
for _, value := range myMap {
fmt.Printf("Value: %d\n", value)
}
- 直接赋值和make函数的区别,其实就是Java中的懒加载机制
- 使用 make 函数 : make 函数会为切片分配底层数组的内存空间,即使长度为 0,也会分配一定的内存,初始时没有元素。
- 直接声明 :直接声明的方式只是创建了一个空切片,底层数组的内存分配会在后续添加元素时进行。
5.条件语句
- Java
String str = "test";
if(str.equals("test")) {
// todo
}
- Go
str := "test"
if str == "test" {
// todo
}
- Java里面判断字符串是否相等需要通过equals判断,那为什么Go可以用==来判断?
- Java : String 是引用类型, == 比较的是对象的引用,而 equals 方法比较的是对象的内容
- Go :字符串是值类型, == 运算符直接比较字符串的内容,因此可以直接使用 == 来判断字符串是否相等。
6.循环语句
- Java 有for和while关键字,还有foreach增强for循环
for(int i = 0; i < 10; i++) {
}
List<Integer> list = new ArrayList<>();
for(Intger num : list) {
}
while(condition) {
}
- Go 只有for这一个关键字 以及range函数遍历
for i := 0; i < 10; i++ {
}
nums := make([]int,0)
for i, num := range nums {
// i是索引位置 num是对应索引位置的元素
}
// 不想要索引位置也可以直接匿名处理
for _, num := range nums {
// _ 当作匿名处理
}
for condition {
}
- Java/Go如何遍历字符串
String str = "hello world";
for(int i = 0; i < str.length(); i++) {
System.out.println(str.charAt(i));
}
str := "hello world"
for index, char := range str {
fmt.Printf("index: %d, char: %c\n", index, char)
}
7.函数声明
- Java
public void test1(String s) {
}
public String test2(String s) {
}
- Go
func test1(s string) {
}
func test2(s string) string {
}
8.函数调用
Java是同个类下的函数式可以直接调用的,Go语言没有类的概念,Go是同个包package下的函数都可以直接调用
- Java 跨类调用需要有staic修饰,可以直接通过类名.调用
class A {
public static String test() {
return "hello world";
}
}
class B {
public static void main(String[] args) {
String res = A.test();
}
}
- Go 跨包调用需要将函数首字母大写,下面的utils包中的Add()函数必须是Add不能是add,Go通过第一个字母大小写来确定访问范围
project/
├── main.go
└── utils/
└── math.go
package utils
// 定义一个导出的函数
func Add(a, b int) int {
return a + b
}
package main
import (
"fmt"
// 导入 utils 包
"project/utils"
)
func main() {
result := utils.Add(1, 2)
}
9.finally / defer
defer是Go语言的特性,简单来说就是一个延迟函数,当函数return的时候会调用
对应的用Java的finally来理解这个defer
- Java 当写了finally之后,只要能走完try前面的代码,这个finally就一定会执行
try {
} catch(Exception e) {
} finally {
// todo
}
- Go
func defer1() {
fmt.println("defer1")
}
func main() {
defer defer1()
fmt.println("main")
return;
}
/**********************/
输出:
main
defer1
一个函数可以有多个defer,多个defer的执行顺序是先进后出LIFO,就跟栈是一样的
func defer1() {
fmt.println("defer1")
}
func defer2() {
fmt.println("defer2")
}
func main() {
defer defer1()
defer defer2()
fmt.println("main")
return;
}
/**********************/
输出:
main
defer2
defer1
10.异常机制error捕获
- Java
try {
} catch(Exception e) {
// todo
}
-
Go
panic就是我们说的出现错误,recover机制是将异常捕获,打印出异常,方便定位错误,一般是用recover和defer搭配捕获异常
func main() {
defer func() {
if error := recover(); error != nil {
fmt.Println("出现了panic,使用recover获取信息:",error)
}
}()
}
panic传递和Java的throw同理,如果当前函数没有捕获该异常,则不断抛给上层函数进行recover()
package main
import "fmt"
func testPanic1() {
fmt.Println("testPanic1上半部分")
testPanic2()
fmt.Println("testPanic1下半部分")
}
func testPanic2() {
defer func() {
recover()
}()
fmt.Println("testPanic2上半部分")
testPanic3()
fmt.Println("testPanic2下半部分")
}
func testPanic3() {
fmt.Println("testPanic3上半部分")
panic("在testPanic3出现了panic")
fmt.Println("testPanic3下半部分")
}
func main() {
fmt.Println("程序开始")
testPanic1()
fmt.Println("程序结束")
}
输出结果
程序开始
testPanic1上半部分
testPanic2上半部分
testPanic3上半部分
testPanic1下半部分
程序结束
11.接口interface
- Java interface 实现了这个接口就必须实现这个接口的所有方法
public class PhoneExample {
// 定义Phone接口
interface Phone {
void call();
void sendMessage();
}
// 定义Apple类实现Phone接口
static class Apple implements Phone {
private String phoneName;
public Apple(String phoneName) {
this.phoneName = phoneName;
}
@Override
public void call() {
System.out.printf("%s有打电话功能\n", phoneName);
}
@Override
public void sendMessage() {
System.out.printf("%s有发短信功能\n", phoneName);
}
}
// 定义HuaWei类实现Phone接口
static class HuaWei implements Phone {
private String phoneName;
public HuaWei(String phoneName) {
this.phoneName = phoneName;
}
@Override
public void call() {
System.out.printf("%s有打电话功能\n", phoneName);
}
@Override
public void sendMessage() {
System.out.printf("%s有发短信功能\n", phoneName);
}
}
public static void main(String[] args) {
Phone a = new Apple("apple");
Phone b = new HuaWei("huawei");
a.call();
a.sendMessage();
b.call();
b.sendMessage();
Apple apple = (Apple) a;
apple.phoneName = "Apple";
apple.call();
apple.sendMessage();
}
}
- Go interface 实现了我的所有接口,那就是我的实现类
package main
import "fmt"
type Phone interface {
Call()
SendMessage()
}
type Apple struct {
PhoneName string
}
func (a Apple) Call() {
fmt.Printf("%s有打电话功能\n", a.PhoneName)
}
func (a Apple) SendMessage() {
fmt.Printf("%s有发短信功能\n", a.PhoneName)
}
type HuaWei struct {
PhoneName string
}
func (h HuaWei) Call() {
fmt.Printf("%s有打电话功能\n", h.PhoneName)
}
func (h HuaWei) SendMessage() {
fmt.Printf("%s有发短信功能\n", h.PhoneName)
}
func main() {
a := Apple{"apple"}
b := HuaWei{"huawei"}
a.Call()
a.SendMessage()
b.Call()
b.SendMessage()
var phone Phone
phone = new(Apple)
phone.(*Apple).PhoneName = "Apple"
phone.Call()
phone.SendMessage()
}
12.Java类/Go结构体
- Java
public class Task {
private int status;
private String name;
public static void main(String[] args) {
Task task1 = new Task(0,"未运行");
Task task2 = new Task();
task2.setStatus(0);
task2.setName("未运行");
}
public Task() {
}
public Task(int status, String name) {
this.status = status;
this.name = name;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
- Go
type Task struct {
Status int8
Name string
}
func NewTaskPtr(status int8, name string) *Task {
return &Task{
Status: status,
Name: name,
}
}
func (task *Task) GetStatus() int8 {
return task.Status
}
func (task *Task) GetName() string{
return task.Name
}
func main() {
task := Task{
Status: 0,
Name: "未运行",
}
fmt.Println("task:{}",task)
}