内容简介:title: go 变量声明初始化、new、makedate: 2019-01-04tags:
title: go 变量声明初始化、new、make
date: 2019-01-04
tags:
- golang
- 变量声明和初始化
- new
- make
categories:
- golang学习
变量的声明和初始化
实验一
起源于大远问,下面的代码会输出什么?
type Person struct { name string age int } func main() { var p Person fmt.Println(p.age) }
按照我之前的理解,报错。因为p只是声明了,并没有初始化。
但是打印出来却是 0
说明Person对象确实初始化了。
实验二
func main() { var p *Person fmt.Println(p) //<nil> fmt.Println(p.age) //panic: runtime error: invalid memory address or nil pointer dereference }
声明一个变量,初始化的内容只跟变量的类型相关
声明了一个 *Person
类型的指针p,说明 p
初始化的内容就是指针的默认值,那就是 nil
了。
打印p.age出错,证明了Person并没有初始化,当然是空指针错误了。
我们可以画图说明下两者的关系
微信图片_20190106203742.jpg
总结
- nil 只能赋值给指针类型的变量,实际上nil就是是指针类型变量的零值。值类型的变量有各自的零值 比如 int 是 0 string 是 ""
- 变量的声明,无论是值类型还是指针类型的变量,声明之后,变量都会占有一块内存,并且被初始化为一个零值,被初始化的内容只跟变量的类型有关(注意:Post,跟*Post是两种类型
var i int // 值类型 因此 i 是 0
var p Person // 值类型 因此 p.title 是“” p.num 是 0
var po Person // 初始化的不是Post类型,而是 Post类型,即指针类型,因此p是nil p.title 会报错
make和new
new 和 make 都可以用来分配空间,初始化类型。他们和上面有什么关系吗?
new(T) 返回的是 T 的指针
func main() { a := new(int) *a = 3 fmt.Printf("%T,%p,%p,%v\n",a,&a,a,a) // *int,0xc000006028,0xc00000a0a8,0xc00000a0a8 b := new(Person) fmt.Printf("%T,%p,%p,%v\n",b,&b,b,b.age) // *main.Person,0xc000006038,0xc000004460,0 c := new(Person) c = &Person{"xuxiaofeng",26} fmt.Printf("%T,%p,%p,%v\n",c,&c,c,c.age) // *main.Person,0xc000006040,0xc0000044a0,26 }
画图表示一下
微信图片_20190106203742.jpg
第三段中,new就相当于下面这两句话
var c *Person c = &Person{"xuxiaofeng",26}
如果我们 new(*Person)
呢,道理还是同样的道理,只是多了一层指针,指针的指针,容易绕晕。
func main() { a := new(*Person) fmt.Printf("%T.%p,%p\n",a,&a,a) // **main.Person.0xc000006028,0xc000006030 //a = Person{} // error //a = &Person{} // error //*a = Person{} //error *a = &Person{"xuxiaofeng",16} fmt.Printf("%T.%p,%p\n",*a,&(*a),*a) // *main.Person.0xc000006030,0xc000004460 fmt.Println((**a).age) }
画图表示一下
微信图片_20190106203742.jpg
make 只能用于 slice,map,channel
make基本使用就不做介绍了,只要注意只能是slice,map,channel,这三种类型就可以了。这三种类型都是引用类型
new slice
我们能否 new([]int)
new一个slice呢?
func main() { a := new([]int) //a[0] = 1 //(type *[]int does not support indexing) //(*a)[0] = 2 // error: index out of range fmt.Println(len(*a),cap(*a)) //0 0 *a = append(*a,1) fmt.Printf("%T\n",a) //*[]int fmt.Println((*a)[0]) //1 }
我们看也是可以的,只是给我们返回了长度和容量都是0的slice,而append之后,slice的底层数据已经不是原来的数组了。
new map
func main() { a := new(map[string]int) (*a)["xuxaiofeng"] =26 //panic: assignment to entry in nil map fmt.Println(*a) }
new chan
func main() { a := new(chan int) go func() { (*a) <- 2 }() t := <-*a fmt.Println(t) } //fatal error: all goroutines are asleep - deadlock! //goroutine 1 [chan receive (nil chan)]:
说明我们创建的chan就是一个nil,还没有初始化,从一个nil中读数据,程序当然会deadlock
总结
new(T) 返回 T 的指针 *T 并指向 T 的零值。
make(T) 返回的初始化的 T,只能用于 slice,map,channel。
p.name 和*p.name
func main() { p := new(Person) //p = Person{"xuxiaofeng",26} //cannot use Person literal (type Person) as type *Person in assignment p.name = "xuxiaofeng" fmt.Println(p) }
p是*Person,是Person的指针,所以不能直接复制,要想复制也要这样 p = &Person{"xuxiaofeng",26}
,但是为什么调用字段的时候就可以 p.name = "xuxiaofeng"
?
如果 x 是可寻址的,&x 的 filed 集合包含 m,x.m 和 (&x).m 是等同的,go 自动做转换,也就是 p.name和 (*p).name调用是等价的,go 在下面自动做了转换。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- c++ 静态变量初始化测验
- Golang Tips: 变量的声明与初始化
- Java与C++变量初始化的对比
- Go语言学习(3) - 变量与初始化
- iOS中定义变量是否初始化的区别
- Go语言笔记 | 03-变量的声明和初始化
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Blog Design Solutions
Richard Rutter、Andy Budd、Simon Collison、Chris J Davis、Michael Heilemann、Phil Sherry、David Powers、John Oxton / friendsofED / 2006-2-16 / USD 39.99
Blogging has moved rapidly from being a craze to become a core feature of the Internetfrom individuals sharing their thoughts with the world via online diaries, through fans talking about their favori......一起来看看 《Blog Design Solutions》 这本书的介绍吧!
XML、JSON 在线转换
在线XML、JSON转换工具
HEX HSV 转换工具
HEX HSV 互换工具