变量的声明 🔗
var i int
var s string
量的声明我们可以通过var关键字,然后就可以在程序中使用。当我们不指定变量的默认值时,这些变量的默认值是他们的零值,比如int类型的零值是0,string类型的零值是"",引用类型的零值是nil。
对于例子中的两种类型的声明,我们可以直接使用,对其进行赋值输出。但是如果我们换成指针类型呢?
package main
import (
"fmt"
)
func main() {
var i *int
*i=10
fmt.Println(*i)
}
$ go run test1.go
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x4849df]
goroutine 1 [running]:
main.main()
/home/itheima/go/src/golang_deeper/make_new/t
从这个提示中可以看出,对于引用类型的变量,我们不光要声明它,还要为它分配内容空间,否则我们的值放在哪里去呢?这就是上面错误提示的原因。
new 🔗
对于上面的问题我们如何解决呢?既然我们知道了没有为其分配内存,那么我们使用new分配一个吧。
func main() {
var i *int
i=new(int)
*i=10
fmt.Println(*i)
}
我们使用new关键字,为引用类型变量分配内存,然后就可以进行赋值了。现在再运行程序,PASS,打印10。
package main
import (
"fmt"
"sync"
)
type user struct {
lock sync.Mutex
name string
age int
}
func main() {
u := new(user) //默认给u分配到内存全部为0
u.lock.Lock() //可以直接使用,因为lock为0,是开锁状态
u.name = "张三"
u.lock.Unlock()
fmt.Println(u)
}
$ go run test2.go
&{{0 0} 张三 0}
这就是new,它返回的永远是类型的指针,指向分配类型的内存地址。
make 🔗
make也是用于内存分配的,但是和new不同。它只用于
- map
- chan
- slice 的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了。
make与new的异同 🔗
同:堆空间分配 不同:make: 只用于slice、map以及channel的初始化, 无可替代;new: 用于类型内存分配(初始化值为0), 不常用