贺胖娇的编程之旅......

go语言圣经-(2)入门-程序结构

2022.03.07

2.1命名

Go语言中的函数名、变量名、常量名、类型名、语句标号和包名等所有的命名,都遵循一个简单的命名规则:一个名字必须以一个字母(Unicode字母)或下划线开头,后面可以跟任意数量的字母、数字或下划线。大写字母和小写字母是不同的:heapSort和Heapsort是两个不同的名字

定义位置

如果一个名字是在函数内部定义,那么它就只在函数内部有效。如果是在函数外部定义,那么将在当前包的所有文件中都可以访问 ##名字的开头字母的大小写 名字的开头字母的大小写决定了名字在包外的可见性。如果一个名字是大写字母开头的(译注:必须是在函数外部定义的包级名字;包级函数名本身也是包级名字),那么它将是导出的,也就是说可以被外部的包访问,例如fmt包的Printf函数就是导出的,可以在fmt包外部访问。包本身的名字一般总是用小写字母。

命名习惯

Go语言程序员推荐使用 驼峰式 命名

go语言关键字

break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var

预定义的名字

内建常量: true false iota nil

内建类型: int int8 int16 int32 int64 uint uint8 uint16 uint32 uint64 uintptr float32 float64 complex128 complex64 bool byte rune string error

内建函数: make len cap new append copy close delete complex real imag panic recover

2.2 声明

go语言主要有四种类型的声明语句,var(变量) const(常量) type(类型) func(函数)
示例:

// Boiling prints the boiling point of water.
package main

import "fmt"

const boilingF = 212.0 //在包一级声明,整个main包里都可访问

func main() {
    var f = boilingF //局部声明,只能在main函数内部访问
    var c = (f - 32) * 5 / 9
    fmt.Printf("boiling point = %g°F or %g°C\n", f, c)
    // Output:
    // boiling point = 212°F or 100°C
}

在包一级声明语句声明的名字可在整个包对应的每个源文件中访问,而不是仅仅在其声明语句所在的源文件中访问。
相比之下,局部声明的名字就只能在函数内部很小的范围被访问

2.3 变量

var 变量名字 类型 = 表达式
其中“类型”或“= 表达式”两个部分可以省略其中的一个

/**
声明单个变量
**/
var name string = "test" //由于已经设置了值、确定了类型,因此这里可以不要string
var nameA = "test" 
nameB := "test1"
var nameC string
	
var a, b, c int //声明一组变量
var d, e, f = "test", 2, false //初始化一组变量
var f, err = os.Open(name) //调用一个函数,由函数返回的多个返回值初始化

2.3.1 简短变量声明

t := 0.0 //简短变量声明
i, j := 0, 1//简短变量声明一组变量,应该限制只在可以提高代码可读性的地方使用
f, err := os.Open(name) //调用一个函数,由函数返回的多个返回值初始化

因为简洁和灵活的特点,简短变量声明被广泛用于大部分的局部变量的声明和初始化。var形式的声明语句往往是用于需要显式指定变量类型的地方,或者因为变量稍后会被重新赋值而初始值无关紧要的地方。

简短变量声明左边的变量可能并不是全部都是刚刚声明的。如果有一些已经在相同的词法域声明过了 ,那么简短变量声明语句对这些已经声明过的变量就只有赋值行为了。

in, err := os.Open(infile) //声明了in和err变量并赋值
// ...
out, err := os.Create(outfile)//声明了out并赋值,对err只有赋值操作
//此时如果再次全部使用,不能编译通过
out, err := os.Open(outfile) // compile error: no new variables
//解决的方法是第二个简短变量声明语句改用普通的多重赋值语句

2.3.2 指针

x := 1          // x初始化为1
p := &x         // 值为取地址的x,那么p的类型为指针,指向x的存储地址
fmt.Println(*p) // "1"
*p = 2          // p指针指向的地址(变量x存储的值)修改为2
fmt.Println(x)  // "2"
//p为指针,*p是一个表达式,对应p指针指向的变量的值

var p *int
fmt.Printf("p is: %v", p) //任何类型的指针的零值是nil:声明一个指针但不赋值,为nil

返回函数局部变量的地址

因为指针包含了一个变量的地址,因此如果将指针作为参数调用函数,那将可以在函数中通过该指针来更新变量的值。

var p = f()

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

fmt.Println(f() == f()) // "false" 

结论

(1)对于聚合类型每个成员——比如结构体的每个字段、或者是数组的每个元素——也都是对应一个变量,因此可以被取地址。
(2)即使变量由表达式临时生成,那么表达式也必须能接受&取地址操作
(3)任何类型的指针的零值都是nil。
(4)指针之间也是可以进行相等测试的,只有当它们指向同一个变量或全部是nil时才相等

零值

如果初始化表达式被省略,那么将用零值初始化该变量,以下列出各种类型变量对应的零值

类型 对应零值
数值类 0
布尔型 false
字符串 ''
接口或引用类型(包括slice、指针、map、chan和函数) nil
数组或结构体等聚合类型 每个元素或字段都是对应该类型的零值
发表评论