可能是java写多了, 总觉得所有新一代高级语言都应该跟java差不多
不过越来越觉得Go就是一个不用写析构函数自带垃圾回收的C , 连Cpp都算不上
- 它没有class的概念
- 它没有private,protected,friendly和public, 虽然可以通过首字母大小写来区分私有还是公有
- 它可以在windows和linux平台上直接编译可执行二进制文件
- 指针和地址 都可以用, 包括指向指针的指针
Go的new实际上是一个内建函数,而不是关键字, 它会分配内存然后返回一个地址(java的new是关键字,返回一个引用)
下面是一个例子
stringAddress := new(string);
fmt.Println(stringAddress);
fmt.Println(*stringAddress);
intAddress := new(int);
fmt.Println(intAddress);
fmt.Println(*intAddress);
boolAddress := new(bool);
fmt.Println(boolAddress);
fmt.Println(*boolAddress);
上面这部分代码会输出
0xc042008220
0xc042008260
0
0xc042008270
false
然后我们通过经典的swap函数来看看go的指针和地址, 感觉跟 C语言 差不多
声明两个整型变量,然后输出一下地址
i:=3;
j:=4;
fmt.Println("these are original addresses:",&i,&j);
可以得到
these are original addresses: 0xc042008278 0xc042008280
然后如果你直接使用swap(a,b)这样的函数是无法交换的, 形参实参什么的概念又来了, 说白了a,b不过是原值的拷贝
func swap(a int , b int ){
fmt.Println("these are copied parameters addresses",&a,&b);
tmp:=a;
a=b;
b=tmp;
}
从输出可以看出, &a 和 &b 的地址跟原地址并不一致
these are copied parameters addresses 0xc0420082a8 0xc0420082b0
然后试试使用指针, 语法跟C有些不同,C语言类型在前 int *a , Go的话类型在后 a *int
swapByAddress(&i,&j);
func swapByAddress(a *int, b *int){
fmt.Println("these are input original addresses",a,b);
tmp:=*a;
*a=*b;
*b=tmp;
}
上面代码会得到
these are input original addresses 0xc042008278 0xc042008280
你会发现a,b的地址跟传入i,j 是一模一样的
如果你对C语言的指针不熟悉的话可以这样理解
指针就是一个存放地址的变量, 所以主函数里传入的是地址, 接收参数的是指针,
直接获取指针的话例如 a 会得到 这个指针变量中存储的地址值
使用 *a 的话可以得到 指针变量a中存储的地址里存储的真实值
所以你也可以理解&符号是取地址符号, *是取值符号
如果把这个函数改成
func swapByAddress(a *int, b *int){
fmt.Println("these are input original addresses",a,b);
tmp:=a;
a=b;
b=tmp;
}
会得到 无法交换 的结果, 这是因为你只是把指针变量a中存储的地址和指针变量b中存储的地址做了一个交换, 但是地址里的值还是原来的值
只不过之前 地址0xc042008278被放在指针变量a中,现在换成了b, 这样毫无意义
而使用 *a 和 *b 才是 “交换 指针变量a 中存储的地址里的数据 和 指针变量b中存储的地址里的数据”
这里我要感谢谭浩强老爷爷… 😛
这个东西甚至连指向指针的指针都跟C一样
//声明一个整型变量
var tmp int = 100;
//声明一个指向整型变量的指针
var pointer *int = &tmp;
//声明一个指向 "整型变量的指针" 的指针 (2级指针)
var poi2poi **int = &pointer;
fmt.Println(pointer,*pointer);
//第二个值是poi2poi指向的地址,也就是上一行代码pointer的值
fmt.Println(poi2poi,*poi2poi,**poi2poi);
输出
0xc0420082f8 100
0xc042004030 0xc0420082f8 100
完整代码如下
package main
import (
"fmt"
)
func main() {
stringAddress := new(string);
fmt.Println(stringAddress);
fmt.Println(*stringAddress);
intAddress := new(int);
fmt.Println(intAddress);
fmt.Println(*intAddress);
boolAddress := new(bool);
fmt.Println(boolAddress);
fmt.Println(*boolAddress);
i:=3;
j:=4;
fmt.Println("these are original addresses:",&i,&j);
i,j = swapByReturn(i,j);
fmt.Println(i,j);
swap(i,j);
fmt.Println(i,j);
//传入i和j的地址
swapByAddress(&i,&j);
fmt.Println(i,j);
//声明一个整型变量
var tmp int = 100;
//声明一个指向整型变量的指针
var pointer *int = &tmp;
//声明一个指向 "整型变量的指针" 的指针 (2级指针)
var poi2poi **int = &pointer;
fmt.Println(pointer,*pointer);
//第二个值是poi2poi指向的地址,也就是上一行代码pointer的值
fmt.Println(poi2poi,*poi2poi,**poi2poi);
}
func swap(a int , b int ){
fmt.Println("these are copied parameters addresses",&a,&b);
tmp:=a;
a=b;
b=tmp;
}
//参数为两个地址 如 0xc042036228 0xc042036230
func swapByAddress(a *int, b *int){
fmt.Println("these are input original addresses",a,b);
tmp:=*a;
*a=*b;
*b=tmp;
}
func swapByReturn(a int, b int)(int,int){
tmp:=a;
a=b;
b=tmp;
return a,b;
}