【读书笔记】第二章 程序结构

函数内声明的实体,函数内部有效;声明在函数外,则在包中有效;声明时,实体第一个字母大小写决定是否跨包。

实体的4个主要的声明:变量,常量,类型,函数。

默认值:
Go中不存在未初始化的变量,其初始值对应于类型的零值;

  • 对于数字是0;
  • 对于布尔值是false;
  • 对于字符串是“”
  • 对于接口和引用类型(slice、指针、map、通道、函数)是nil;
  • 对于一个像数组或结构体的符合类型,零值是其所有元素的零值;

包级别的初始化是在main开始之前进行;局部变量初始化和声明一样在函数执行期间初始化。

概念:
短变量声明::=,短变量声明最少声明一个新变量;

使用短变量声明时,如下:

in, err := os.Open(file)
out, err := os.Create(outfile)

第一条声明了in和err,而第二条仅声明了out,第二条中的err被当作赋值处理

多重赋值:

i, j = j, i //交换i和j的值

按照说法,在实际更新变量前,右边所有的表达式将会被推演???何为推演???

Go中的指针:
不是所有的值都有地址,但是所有的变量都有。
指针的值是可比较的,当且仅当两个指针指向同一个变量或者两个指针都是nil的情况下才相等。

var p := f()
func f() *int {
    v := 1
    return &v
}

需要注意的是返回局部变量的地址是安全的,此时局部变量在调用返回后仍然存在指针p依然引用它;但是每次调用都会返回不同的值,即f() != f()
会产生副作用的语句(即传递地址,使函数内的改变对外可见):

func incr(p *int) int {
    *p++
    return *p
}
v := 1
incr(&v)    // v = 2
incr(&v)    // v = 3

此处对于本书的P25页有不懂的地方

new
创建实体的时候直接创建指针类型的实体:使用new

p := new(int)   // int类型的p,指向未命名的int变量

new是一个预声明的函数,而不是一个关键字。因此可以当作变量名使用:

func delta(old, new int) int (return old + new)  // 在该函数中内置的new函数变的不可用

变量的生命周期与高效程序:

var global *int
func f() {
    var x int
    x = 1
    global = &x
}

此时称x从f中逃逸;x可以断定是分配在堆空间的。
类型声明:

type name underlying-type

典型的例子是标准库time包里的一个类型的声明:

type Duration int64

需要注意的是,尽管底层类型相同,它们也不是相同的数据类型;

type Celsius flout64
type Fahrenheit flout64

即,Celsius与Fahrenheit不是相同的数据类型,需要进行显示的类型转换。
若二者具有相同的底层类型或二者都是指向相同底层类型变量的未命名指针类型,则二者是可以相互转换的。

如下面的例子所示:

package main

type Duration int64

func main() {
    var dur Duration
    dur = int64(1000)   //  编译出错
}

P33,种群统计算法不理解

包初始化:
定义多个init函数,数量可以有多个,按照声明的顺序自动执行(在main执行之前先执行初始化)。

补充:

2019/01/08

有下面的包导入格式:

_ "day2/pkg1"

前面的_表示对包进行初始化操作,但是不使用包内的标识符,程序将会调用包内所有代码文件中里定义的init()函数。

此条目发表在编程语言分类目录。将固定链接加入收藏夹。

发表评论

电子邮件地址不会被公开。 必填项已用*标注