go声明和初始化
go声明和初始化
当我们第一次看见变量和声明时,我们仅仅看见一些内置的类型,比如整型和字符串。现在我们将学习结构体,并且我们会深入学习包括指针的内容。
通过一种最简单的方式去创建一个结构体值类型:
goku := Saiyan{
Name: "Goku",
Power: 9000,
}
注意:上面的结构体中,结尾的逗号,
是不能省的。如果没有逗号,编译器会给出一个错误。你将喜欢上这种一致性要求,特别是如果你已经使用一种相反的语言或格式。
我们不需要给结构体设置任何值甚至任何字段。这2中方式都是有效的:
goku := Saiyan{}
// 或者
goku := Saiyan{Name: "Goku"}
goku.Power = 9000
这就像一个未赋值的变量一样,结构体的字段也会有一个0值。
另外,你也可以省略字段的名字,按字段的顺序进行声明(尽管为了简洁起见,你尽量在结构体只有少量字段时才使用这种方式):
goku := Saiyan{"Goku", 9000}
上面的例子主要是声明了一个变量goku
,并给它赋值。
尽管在大多数时候,我们不希望一个变量直接关联一个值,而是希望一个指针指向变量的值。指针是一个内存地址。通过指针可以找到这个变量实际的值。这是一种间接的取值。严格地说,这与存在一个房子并指向另外一个房子有一些区别。
为什么我们需要一个指针指向一个值,而不需要一个实际值。这主要是因为在go语言中,函数的参数传递都是按值传递,即传递的是一个拷贝。了解到这点,下面程序会打印什么?
func main() {
goku := Saiyan{"Goku", 9000}
Super(goku)
fmt.Println(goku.Power)
}
func Super(s Saiyan) {
s.Power += 10000
}
答案是9000,不是19000。为什么?因为Super
只是改变了goku
的一个拷贝,所以在Super
中的改变不会调用者中反应出来。如果你希望答案是19000,我们需要传递一个指向我们值的指针:
func main() {
goku := &Saiyan{"Goku", 9000}
Super(goku)
fmt.Println(goku.Power)
}
func Super(s *Saiyan) {
s.Power += 10000
}
我们改变了2个地方。首先是使用了&
操作符去获得我们值的地址(&
叫取地址符)。接下来,我们改变了Super
接受的参数类型。之前我们是传递一个Saiyan
的值类型,现在我们传递了一个地址类型*Saiyan
,这里的*X
表示一个指向类型X
的一个指针。显而易见,Saiyan
和*Saiyan
类型之间有一定的联系,但是它们是两种不同的类型。
需要指出的是,我们现在传递给Super
参数的仍然是goku
的值拷贝。只是现在goku
的值变成了一个地址。这个地址拷贝和源地址相同。可以认为它类似一个指向餐厅方向的拷贝,这就间接服务于我们。虽然是一个拷贝,但是和源地址一样,也指向同一个餐厅。
我们能证明这是一个拷贝,通过试着去改变它指向的地方(这可能不是你想做的):
func main() {
goku := &Saiyan{"Goku", 9000}
Super(goku)
fmt.Println(goku.Power)
}
func Super(s *Saiyan) {
s = &Saiyan{"Gohan", 1000}
}
上面的代码在此输出了9000。很多语言也有类似的行为,包括ruby、python、java和c#。go某种程度上和c#一样,只是让事实可见。
显而易见,复制一个指针变量的开销比复制一个复杂的结构体小。在一个64的系统上,指针的大小只有64位。如果我们的结构体有很多字段,创建一个结构体的拷贝会有很大的性能开销。指针的真正意义就是通过指针可以共享值。我们想通过Super
去改变goku
的拷贝或者改变共享的goku
值本身?
这里不是说你需要一直使用指针。本章的结尾,在我们学到更多关于结构体使用的内容之后。我们将重新审视值类型和指针类型的问题。
本文转自:http://codingdict.com/article/22523
原文地址:https://www.cnblogs.com/bczd/p/11983138.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法