Dra-M Dra-M
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

莫小龙

保持理智,相信未来。
首页
技术
冥思
哲学
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • Java

  • Golang

    • GitLab私服+Go Modules踩坑经验(SSH自定义端口)
    • 【代码片段】我使用的Gin中间处理器(自定义异常处理、日志打印、traceId、跨域配置)
    • 【Java转Go】如何理解Go中的值类型、引用类型、nil
    • 【Java转Go】如何理解面向对象,怎么把Golang用成面向对象的样子
    • Golang 调度器 GMP 原理与调度全分析
    • Go中GMP有哪些状态?
    • 一文搞懂go gc垃圾回收原理
    • Go什么时候发生阻塞?阻塞时,调度器会怎么做?
    • Go netpoller 原生网络模型之源码全面揭秘
    • Goroutine 泄露 - 被遗忘的发送者
    • go map 设计与实现
    • go slice 设计与实现
    • 小白也能看懂的context包详解:从入门到精通
    • go interface 设计与实现
    • 深入理解 go chan
    • go chan 设计与实现
    • 深入理解 go Mutex
    • 深入理解 go sync.Map - 基本原理
    • go sync.Map 设计与实现
    • 深入理解 go sync.Once
    • 深入理解 go reflect - 反射基本原理
    • 深入理解 go reflect - 要不要传指针
  • 编程思想

  • 微服务

  • 中间件

  • Python

  • 运维

  • 技术
  • Golang
莫小龙
2022-12-03

【Java转Go】如何理解Go中的值类型、引用类型、nil

Java的赋值和参数传递都是值拷贝,Golang也是如此。

Java的值类型只有8种:long、int、short、byte、float、double、char、boolean。其他所有类型均为引用类型。

Golang的引用类型只有6种:map、pointers、slice、channel、interface、function。其他所有类型,包括struct,均为值类型。

数据类型本质是固定内存大小的别名

数据就是那些内存中代码段,不是0就是1,只不过不同的读取与解释方式让它有了不同的意义(数据类型亦或指令类型) 。这不同的读取与解释的方式,便是类型的本质。

当操作值类型时,是以某一值类型的方式去解释某段内存数据。

当读引用类型时,是以引用的方式解释某段内存空间,再以引用类型的方式解释引用指向的内存空间。

参数传递是一种赋值,将传递的变量赋值给参数变量。

在Java和Golang中赋值都是值拷贝,对拷贝的值操作不会影响原来的值。

    public static void main(String[] args) {
        int i = 1;
        int j = i;
        i = 2;
        //2
        System.out.println(i);
        //1
        System.out.println(j);
    }
1
2
3
4
5
6
7
8
9
func main() {
	i := 1
	j := i
	i = 2
	//2
	println(i)
	//1
	println(j)
}
1
2
3
4
5
6
7
8
9

当类型为引用类型时,拷贝的是引用,两个引用的值相同,指向同一块内存区域,当操作对应数据时,操作的是同一块数据。

Java不能显式的操作引用,值类型外的都是引用。

    public static void main(String[] args) {
        MyInt myIntI = new MyInt();
        myIntI.num = 1;
        MyInt myIntJ = myIntI;
        myIntI.num = 2;

        //2
        System.out.println(myIntI.num);
        //2
        System.out.println(myIntJ.num);
    }
1
2
3
4
5
6
7
8
9
10
11

这里特殊提一下,Java的包装类(Integer等),会自动拆装箱,意味着Integer本身虽然是引用类型,但赋值操作时会拆箱为基本的int类型,再包装成一个新的Integer传递。

    public static void main(String[] args) {
        Integer i = 1;
        Integer j = i;
        i = 2;
        //2
        System.out.println(i);
        //1
        System.out.println(j);
    }
1
2
3
4
5
6
7
8
9

Java的String类型则是遵循不可变原则,里面有一些魔法。当你赋值/修改字符串时可能会赋值一个现成缓存的引用,或新创建空间的引用,但永远不会在原有空间上做修改。

Golang可以通过&取到引用,通过对引用*取到所指的数据。

func main() {
	//int类型
	i := 1
	//*int类型
	j := &i
	i = 2
	//2
	println(i)
	//0xc000061f60
	println(&i)
	//2
	println(*j)
	//0xc000061f60
	println(j)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

需要强调的是,Golang结构体拷贝,是值拷贝,其中的引用类型拷贝的是引用地址,也就是浅拷贝,这里容易踩坑。

type MyStruct struct {
	np *int
	n  int
}
func main() {
	i := 1
	myStructI := MyStruct{np: &i, n: 2}
	myStructJ := myStructI

	//0xc000061f60
	println(&myStructI)
	//0xc000061f38
	println(myStructI.np)
	//0xc000061f50
	println(&myStructJ)
	//0xc000061f38
	println(myStructJ.np)
	//0xc000061f68
	println(&myStructI.n)
	//0xc000061f58
	println(&myStructJ.n)
	*myStructJ.np = 3
	myStructJ.n = 4
	//3
	println(*myStructI.np)
	//2
	println(myStructI.n)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

空指针,是用引用的方式解释某段值为0的空间。

只有引用类型可能出现空指针。类型声明意味着开辟一块固定大小的内存空间并写满0,任何值类型的全0都是合法默认值(如int的0,bool的false),只有引用的全0是空的意思。


#Golang#Java转Go
上次更新: 10/23/2024
【代码片段】我使用的Gin中间处理器(自定义异常处理、日志打印、traceId、跨域配置)
【Java转Go】如何理解面向对象,怎么把Golang用成面向对象的样子

← 【代码片段】我使用的Gin中间处理器(自定义异常处理、日志打印、traceId、跨域配置) 【Java转Go】如何理解面向对象,怎么把Golang用成面向对象的样子→

最近更新
01
mosquito配置ws协议
10-23
02
Pip包的离线下载和安装
10-23
03
stable diffusion 相关收藏
02-24
更多文章>
Theme by Vdoing | Copyright © 2019-2024 Dra-M
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式