2.1命名
-
以一个字母或下划线开头
-
关键字不能作为名字
2.2 声明
- 四种声明语句:var const type func
2.3 变量
var 变量名字 类型 = 表达式
类型或表达式只需要写一个就行了,都写也没关系
如果表达式没有将自动将该类型的零值赋给该变量
可以初始化一组变量
var i,j,k int
var i,j,k = true,2,"four"
:=
声明并且赋值,如果左侧一些变量已经声明过,就仅赋值
2.3.2 指针
指针之间只有当他们指向同一个变量或者全部是nil才相等
注意:nil不是零值
通过指针来更新变量的值
var p =f()
func f() *int{
v :=1
return &v
}
如果将指针作为参数调用函数,可以在函数中通过该指针来更新变量的值
当我们对某个指针所指向的值进行操作的时候,指针不改变
*p++
指针是实现flag包的关键技术,它使用命令行参数来设置对应变量 的值,而这些命令行的标志参数可能会零散分布在整个程序中
设置一个flag通常包括三个属性:
-
命令行标志参数的名称
-
默认值
-
标志参数对应的描述信息
package main
import (
"flag"
"fmt"
"strings"
)
var n = flag.Bool("n", false, "omit trailing the new line")
var sep = flag.String("s", " ", "separator")
//至于n和sep所定义的功能是函数内部已经实现了的
// flag.Bool and flag.String
func main() {
flag.Parse()//
fmt.Print(strings.Join(flag.Args(), *sep))
if !*n {
fmt.Println()
}
}
new(T)类似于语法糖,不提供新的功能,只是一种语法形式,让代码看起来舒服
每次调用new函数,返回的都是一个新变量的地址
p:=new(int)//int类型的指针
q := new(int)
fmt.Println(p==q) //false
Go语言的自动垃圾收集器是如何知道一个变量何时可以被回收?
抛开技术问题不说,基本的实现思路是,从每个包级的变量和每个当前运行函数的每一个局部变量开始,通过指针的访问路径遍历,是否能找到该变量。如果不存在这样的访问路径,说明该变量不可达,这样的变量也就没有存在的意义
这里我们需要讨论逃逸的变量
var global *int
func f(){
var x int
x = 1
global = &x
}
func g() {
y :=new(int)
*y =1
}
f函数里的x变量必须在堆上分配,因为它最终会逃逸到global这个变量里面中去。
2.5类型
type 类型名字 底层类型
新命名类型提供了一个方法,用来分割不同概念的类型,即使他们呢底层类型相同也是不兼容的
不可以相互比较或混在一个表达式中运算
许多类型都会定义一个String方法,当使用fmt包的时候,会自动调用对应的String方法进行打印