命名
Go命名规则与其他语言类似:字母或下划线开头,后面可以跟字母、数字和下划线;大小写敏感;不能与保留字冲突。
Go有25个关键字:
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
Go还有一个特性,名字的首字母是否大写决定该实体是否对其它包可见,例如fmt包的Printf函数就可被其它包导入使用。
声明
A declaration names a program entity and specifies some or all of its properties.
Go有4种主要的声明:var, const, type, and func。Go程序源代码文件以.go结尾,其结构大致如下:
//包声明
package main
//导入包声明
import "fmt"
//包级别常量声明
const boilingF = 212.0
//函数声明
func main() {
//本地变量声明
var f = boilingF
var c = (f - 32) * 5 / 9
fmt.Printf("boiling point = %g°F or %g°C
", f, c)
// Output:
// boiling point = 212°F or 100°C
}
Go函数声明有点不太习惯,主要是函数返回值声明放到最后了,其形式如下:
func fToC(f float64) float64 {
return (f - 32) * 5 / 9
}
变量
Go变量声明的标准形式如下:
var name type = expression
Go变量一定有初始化值,如果定义时没有初始化,则赋“0值”。特别的是string的0值是"",接口和引用类型的0值是nil。
Go可以一次声明和初始化多个变量:
var i, j, k int // int, int, int
var b, f, s = true, 2.3, "four" // bool, float64, string
短变量声明语法(short variable declarations)
Go为函数内局部变量声明提供了一个简短的声明方式:
name := expression
例如:
anim := gif.GIF{LoopCount: nframes}
freq := rand.Float64() * 3.0
t := 0.0
短变量声明有个细节:它不需要声明左边的每一个变量,但至少要声明一个新变量。若某个变量已经在同一词法块中(lexical block)声明过,对这个变量而言相当于赋值。
in, err := os.Open(infile)
// ...
out, err := os.Create(outfile) //out是声明,err是赋值。
指针
A variable is a piece of storage containing a value.
A pointer value is the address of a variable.
指针提供了间接访问变量的方式。指针指向变量的地址,而且可以访问该地址的内容,相当于修改了变量的值,所以叫“间接访问”。
因为地址大小是固定的,所以指针类型也是固定的,都是 *int。
对变量x进行“取址”操作,p:=&x,就能得到指向x的指针值;对指针变量进行指针操作,可以访问对应的变量。
x := 1
p := &x // p, of type *int, points to x
fmt.Println(*p) // "1"
*p = 2 // equivalent to x = 2
fmt.Println(x) // "2"
变量的生存期(lifetime)
包级别的变量的生存期是整个程序运行期。局部变量的生存期:从声明语句执行开始,到该变量不可达为止,不可达时以为着可能被GC。函数参数和返回值也是局部变量。
由于变量的生存期只由是否可达决定,所以某局部变量可能在函数返回后依然存活。编译器可能选择在堆或栈上分配内存,不管该变量是var声明还是new函数声明。
var global *int
func f() {
var x int
x = 1
global = &x
}
func g() {
y := new(int)
*y = 1
}
类型声明(Type Declarations)
type 声明可以根据已存在的类型定义一种新的具名类型,新的类型。使用type类型的原因是需要更明确某个变量的业务含义。如温度计量,有摄氏度和华氏度,如果仅用float64来表示,业务上不够明确,因此可以分别定义出两个新的type类型:
// Package tempconv performs Celsius and Fahrenheit temperature computations.
package tempconv
import "fmt"
type Celsius float64
type Fahrenheit float64
const (
AbsoluteZeroC Celsius = -273.15
FreezingC Celsius = 0
BoilingC Celsius = 100
)
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }